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

implement exec.split #81

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

implement exec.split #81

wants to merge 6 commits into from

Conversation

maikel
Copy link
Collaborator

@maikel maikel commented Nov 16, 2024

This PR tracks my progress in implementing exec.split.

@maikel maikel marked this pull request as draft November 16, 2024 19:41
@maikel maikel force-pushed the exec.split branch 2 times, most recently from a14ccc2 to b16afd5 Compare November 18, 2024 04:26
@maikel maikel marked this pull request as ready for review November 23, 2024 10:33
@maikel maikel changed the title Draft: implement exec.split implement exec.split Nov 23, 2024
Copy link
Collaborator

@dietmarkuehl dietmarkuehl left a comment

Choose a reason for hiding this comment

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

Last week I didn't get around doing any review (the C++ committee meeting was busy till late on all the days) and I haven't reviewed all the code, yet. However, I have a few comments.

//!
//! @tparam Item The type of the item in the stack.
//! @tparam Next The pointer to the next item in the stack.
template <class Item, Item* Item::*Next>
Copy link
Collaborator

Choose a reason for hiding this comment

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

In the past compilers were pretty bad optimising anything around pointer to members. They tend to be way better at optimising around inline functions and the parameter could be something like

decltype([](auto* node){ return node->next; })

This lambda could also be a default argument if the objective is avoiding the need to specify it. Admittedly, using this approach is more involved when actually using the data structure. This comment is primarily for consideration and doesn't necessarily need to be addressed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I will investigate code gen. Now I am curious

} else {
assert(!head_ && !last_);
head_ = item;
last_ = item;
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems this assignment needs to be outside of the else-branch: if last_ wasn't nullptr before the operation, item also becomes the new last_ element.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I guess this class implementation is not sound and wrong for the general case. In split I just call pop and call it a day but it can't stay like this. I might make this a class containing single pointer only that you can iterate through.

Good catch.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think split just needs a list of items and the order doesn't matter. Moving it to an intrusive_stack rather than an intrusive_queue would be fine. I guess the use in split works with the current implementation but other uses, if they energe, might not.

~intrusive_queue() { assert(!head_); }

//! @brief Pushes an item to the queue.
auto push(Item* item) noexcept -> void {
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems there should either be a precondition assert(not item->next) (if the operation pushes just one element) or before updating last the list of items hanging off item needs to be walked.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes I was lazy and introduced bugs. Whatever I pop in atomic_intrusive_queue is a singly linked list that I want to traverse. I will revise this

Comment on lines +59 to +62
local_state_base(const local_state_base&) = delete;
local_state_base(local_state_base&&) = delete;
auto operator=(const local_state_base&) -> local_state_base& = delete;
auto operator=(local_state_base&&) -> local_state_base& = delete;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I have recently introduced a base class ::beman::execution26::detail::virtual_immovable which provides this boiler plate: some of the clang-tidy checks insisted in that stuff being written which is quite annoying. The class is currently possibly in the wrong header (immovable.hpp).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Note that I think it is more "efficient" to define a protected destructor and make the derived class final. But I can just switch to virtual immovable.

NB. I run clang-tidy and cppcheck locally and it still complains on classes using virtual_immovable. Although I have to check which one complains. Would be good to use the same tooling consistently in CI and local dev.

@maikel
Copy link
Collaborator Author

maikel commented Nov 24, 2024

Quick feedback is great. I think i should expand the tests anyway to cover more properties and usecases.

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