-
Notifications
You must be signed in to change notification settings - Fork 81
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FIX] Fixes aligned allocator issue for non posix implementation of aligned_alloc. #1362
Conversation
rrahn
commented
Nov 7, 2019
- Uses operator new and delete instead of aligned_alloc.
Codecov Report
@@ Coverage Diff @@
## master #1362 +/- ##
==========================================
+ Coverage 97.51% 97.55% +0.03%
==========================================
Files 224 226 +2
Lines 8731 8781 +50
==========================================
+ Hits 8514 8566 +52
+ Misses 217 215 -2
Continue to review full report at Codecov.
|
79ed7ce
to
1dd9b31
Compare
*/ | ||
template <typename new_value_type> | ||
struct rebind | ||
{ | ||
//!\brief The alignment for the rebound allocator. | ||
static constexpr size_t other_alignment = (alignof(new_value_type) > alignment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::max ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some questions and some suggestion and some love
@@ -80,6 +80,68 @@ TEST(aligned_allocator, memory_alignment) | |||
alloc.deallocate(begin, size); | |||
} | |||
|
|||
TEST(aligned_allocator, memory_alignment_new_extended) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does new_extended
mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is language from the c++ draft. It means that it's alignment is bigger than the value of __STDCPP_DEFAULT_NEW_ALIGNMENT__
alignas(64) std::array<int32_t, 2> data{}; | ||
}; | ||
|
||
TEST(aligned_allocator, memory_alignment_new_extended_default) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does new_extended_default
mean?
EXPECT_EQ(memory_alignment(begin, alignment), 0u); | ||
EXPECT_EQ(memory_alignment(end, alignment), 0u); | ||
|
||
EXPECT_EQ(memory_alignment(begin + 1, alignment), 0u); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it always 0? I don't want to think :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
because it does not use a larger alignment than the alignment of the type that is allocated for (which is 64 bytes). So every value starts at 64 byte boundary. Also that's why I called this test default to show the behavior of a new extended type where we use the default alignment of the type and not a larger one.
* This class allocates memory at the given alignment boundary. If the specified `alignment` is not supported by the | ||
* used allocation method a std::bad_alloc exception will be thrown. For requested alignments larger than | ||
* `__STDCPP_DEFAULT_NEW_ALIGNMENT__` the storage will have the alignment specified by the value `alignment`. | ||
* Otherwise, the storage is aligned for any object that does not have new-extended alignment and is of the requested |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is new-extended? Can you link it to some cppreference page?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And is the other one not of the requested size?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you give some examples which "objects" might be effected by the else case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like everything up to __STDCPP_DEFAULT_NEW_ALIGNMENT__
bytes. IIRC that is 16 byte. But I look into this and extend the example with some comments. I guess it shows this already.
* [__STDCPP_DEFAULT_NEW_ALIGNMENT__](https://en.cppreference.com/w/cpp/memory/new/align_val_t) the alignment | ||
* aware operator new that takes as second argument the alignment as std::align_val_t. The allocation methods | ||
* used by the global operator new functions is unspecified, e.g. std::malloc or std::aligned_alloc. Accordingly, | ||
* the requirements on the alignment and the size of allocated bytes is implementation defined. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this has any impact on the intended behaviour of this class?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand you question. Could you be more specific? I mean this is the same problem when to use std::aligned_alloc. Depending on how operator new is implemented and depending on the platform different things are possible. So for example it might still be a problem in the future, that on an architecture that uses posix mem_align arbitrary sizes of bytes to allocate can be used, while on others this might be restricted to sizes that are a multiple of the alignment. But that is implementation defined and beyond the scope of this class. It only makes sure that it calls aligned memory, where it uses whatever ::operator new(n)
uses to align up to alignments of __STDCPP_DEFAULT_NEW_ALIGNMENT__
and beyond that aligns the memory depending on whatever ::operator new(n, alignment)
uses.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: We call the new operator with the semantic requirements that the c++ standard specifies/demands, but be aware that users can overload any (global) ::operator new
that might not adhere to the standard and might cause std::bad_alloc or unaligned pointers.
…ligned_alloc. * Uses operator new and delete instead.
1dd9b31
to
90dfea7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! One thing left.
@@ -28,6 +28,12 @@ namespace seqan3 | |||
* | |||
* \details | |||
* | |||
* This class allocates memory at the given alignment boundary. If the specified `alignment` is not supported by the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you always use the term memory-alignment
instead of just alignment
like in the documentation below? It helps to know up front that this has nothing to do with our pairwise alignment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a section about what memory alignment is.
* used allocation method a std::bad_alloc exception will be thrown. For requested alignments larger than | ||
* `__STDCPP_DEFAULT_NEW_ALIGNMENT__`, also called new-extended alignments, the storage will have the alignment | ||
* specified by the value `alignment`. Otherwise, the storage is aligned for any object that does not have new-extended | ||
* alignment, e.g. int or double, and is of the requested size. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From this text, I do not understand what a memory alignment
is.
If you think this is common knowledge, can you give just me an explanation? If not, one or few sentences would be great since this is a public interface.
Side note: I see that the number is always a multiple of the word size. Is this required and if so do you static_assert this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side note: I see that the number is always a multiple of the word size. Is this required and if so do you static_assert this?
I am not sure I understand what do you mean?
* [operator new](https://en.cppreference.com/w/cpp/memory/new/operator_new). | ||
* If the given `alignment` is bigger than | ||
* [__STDCPP_DEFAULT_NEW_ALIGNMENT__](https://en.cppreference.com/w/cpp/memory/new/align_val_t) the alignment | ||
* aware operator new that takes as second argument the alignment as std::align_val_t. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this sentence is mal formatted... at least I cannot make sense of it
* \details | ||
* | ||
* The argument n must be equal to the first argument of the call to allocate() that originally produced p; | ||
* otherwise, the behavior is undefined. | ||
* The argument `n` must be equal to the first argument of the call to seqan3::aligned_allocator::allocate that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems error prone? Can't we cache n
and remove the parameter from this function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is defined and documented according to the allocator interface requirements: https://en.cppreference.com/w/cpp/named_req/Allocator, and I am afraid we need to keep this interface.
@@ -47,6 +48,12 @@ TEST(aligned_allocator, conversion_constructor) | |||
[[maybe_unused]] aligned_allocator<float, 16> float_alloc{int_alloc}; | |||
} | |||
|
|||
TEST(aligned_allocator, request_to_much_memory) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TEST(aligned_allocator, request_to_much_memory) | |
TEST(aligned_allocator, request_too_much_memory) |
💅
…ligned_alloc. (seqan#1362) * [FIX] Fixes aligned allocator issue for non posix implementation of aligned_alloc. * Uses operator new and delete instead.