Skip to content
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

P1144 #1

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open

P1144 #1

wants to merge 11 commits into from

Conversation

Quuxplusone
Copy link
Owner

No description provided.

@@ -154,7 +154,7 @@ inline void p_free(void* ptr) {
// std::vector<int, parlay::allocator<int>>
//
template <typename T>
struct allocator {
struct PARLAY_TRIVIALLY_RELOCATABLE allocator {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This annotation isn't needed, AFAICT. allocator is a Rule-of-Zero type with no data members. (Its templated constructor doesn't matter because it still has an implicitly defaulted copy ctor and move ctor.)

Comment on lines 357 to 358
// Container implementations can differ widely by vendor, so we don't want to specialize these
// with a broad brush. Instead, only specialize them for stdlibs that we are confident about.
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, https://quuxplusone.github.io/blog/2019/02/20/p1144-what-types-are-relocatable/ — although I'd encourage you to do less of this warranting-of-types-you-don't-own, because this is exactly how Folly got in trouble. 😛 Of course it makes a difference for performance (iff you're not using a P1144-enabled STL implementation to begin with). The good news is that you've guarded this all under PARLAY_MUST_SPECIALIZE_IS_TRIVIALLY_RELOCATABLE, so if there are any bugs, my P1144 implemention will fix them rather than cause them. ;)

Comment on lines 340 to 341
template<typename T, typename Deleter>
PARLAY_ASSUME_TRIVIALLY_RELOCATABLE_IF((is_trivially_relocatable_v<Deleter>), std::unique_ptr<T, Deleter>);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Technically you also need to check is_trivially_relocatable_v<Deleter::pointer>; or just drop the Deleter arg the way you dropped the allocator from all the STL containers below.

Comment on lines 337 to 338
template<typename T>
PARLAY_ASSUME_TRIVIALLY_RELOCATABLE(std::optional<T>);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong; you need IF(is_trivially_relocatable_v<T>).

if constexpr (!std::is_trivially_default_constructible_v<T>) {
uninitialized<T> holder;
std::memcpy(&holder.value, src, sizeof(T));
return holder.value;
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like overengineering. IIUC the whole point of this bits_to_object is you're trying to avoid the "move and destroy" codepath in relocate below. But return holder.value won't copy-elide, so you'll get a move anyway. In fact you'll get a copy anyway, won't you?!
So unless I'm mistaken, this is a pessimization and also must be lacking test coverage for unique_ptr or any other trivially-relocatable-but-non-copyable type.

using reference = std::add_lvalue_reference_t<value_type>;
using pointer = std::add_pointer_t<value_type>;

uninitialized_iterator_adapter(Iterator it_) : it(it_) {}
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: explicit


reference operator*() const { return it->value; }

pointer operator->() { return std::addressof(it->value); }
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const (right?)

//
// The resulting iterator will have the same iterator category as Iterator.
template<typename Iterator>
class uninitialized_iterator_adapter {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: ISO (and me) spell it adaptor, although the dictionary accepts both ways.
https://en.cppreference.com/w/cpp/experimental/resource_adaptor

@@ -219,7 +219,7 @@ sequence<size_t> integer_sort_r(slice<InIterator, InIterator> In,
// uninitialized_relocate_n, which can memcpy multiple elements at a time
// to save on performing every copy individually.
if constexpr (std::is_same_v<assignment_tag, uninitialized_relocate_tag>) {
uninitialized_relocate_n(Out.begin(), In.begin(), Out.size());
parlay::uninitialized_relocate(In.begin(), In.end(), Out.begin());
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throughout: I guess In.size() == Out.size()? which is also known as n? You switch from Out.size() on the left to In.end() on the right, so they better be the same size.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants