Commit daee4696 by FritzFlorian

Allow deque usage with and without callback.

This seems to be only possible with two different function names, as variadic arguments and default arguments wont work together.
parent 51b919f0
...@@ -81,8 +81,10 @@ class work_stealing_deque { ...@@ -81,8 +81,10 @@ class work_stealing_deque {
tail_{other.tail_.load()}, tail_{other.tail_.load()},
previous_tail_{other.previous_tail_} {} previous_tail_{other.previous_tail_} {}
template<typename T, typename ...ARGS>
T *push_tail(ARGS &&... args);
template<typename T, typename Function, typename ...ARGS> template<typename T, typename Function, typename ...ARGS>
T *push_tail(const Function &after_creation, ARGS &&... args); T *push_tail_cb(const Function &after_creation, ARGS &&... args);
Item *pop_tail(); Item *pop_tail();
Item *pop_head(); Item *pop_head();
......
...@@ -37,8 +37,14 @@ std::pair<work_stealing_deque_item, T> *work_stealing_deque<Item>::allocate_item ...@@ -37,8 +37,14 @@ std::pair<work_stealing_deque_item, T> *work_stealing_deque<Item>::allocate_item
} }
template<typename Item> template<typename Item>
template<typename T, typename ...ARGS>
T *work_stealing_deque<Item>::push_tail(ARGS &&... args) {
return push_tail_cb<T>([](T *) {}, std::forward<ARGS>(args)...);
}
template<typename Item>
template<typename T, typename Function, typename ...ARGS> template<typename T, typename Function, typename ...ARGS>
T *work_stealing_deque<Item>::push_tail(const Function &after_creation, ARGS &&... args) { T *work_stealing_deque<Item>::push_tail_cb(const Function &after_creation, ARGS &&... args) {
static_assert(std::is_same<Item, T>::value || std::is_base_of<Item, T>::value, static_assert(std::is_same<Item, T>::value || std::is_base_of<Item, T>::value,
"Must only push types of <Item> onto work_stealing_deque<Item>"); "Must only push types of <Item> onto work_stealing_deque<Item>");
......
...@@ -50,7 +50,7 @@ void task::spawn_child(ARGS &&... args) { ...@@ -50,7 +50,7 @@ void task::spawn_child(ARGS &&... args) {
ref_count_++; ref_count_++;
// Push on our deque // Push on our deque
thread_state::get()->deque_.push_tail<T>([this](T *item) { thread_state::get()->deque_.push_tail_cb<T>([this](T *item) {
// Assign forced values (for stack and parent management) // Assign forced values (for stack and parent management)
item->parent_ = this; item->parent_ = this;
item->deque_state_ = thread_state::get()->deque_.save_state(); item->deque_state_ = thread_state::get()->deque_.save_state();
......
...@@ -143,12 +143,11 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct ...@@ -143,12 +143,11 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct
work_stealing_deque<int> deque{&stack}; work_stealing_deque<int> deque{&stack};
int one = 1, two = 2, three = 3, four = 4; int one = 1, two = 2, three = 3, four = 4;
auto no_op = [](int *) {}; // Empty-Callback
SECTION("add and remove items form the tail") { SECTION("add and remove items form the tail") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
deque.push_tail<int>(no_op, three); deque.push_tail<int>(three);
REQUIRE(*deque.pop_tail() == three); REQUIRE(*deque.pop_tail() == three);
REQUIRE(*deque.pop_tail() == two); REQUIRE(*deque.pop_tail() == two);
...@@ -156,17 +155,17 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct ...@@ -156,17 +155,17 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct
} }
SECTION("handles getting empty by popping the tail correctly") { SECTION("handles getting empty by popping the tail correctly") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
REQUIRE(*deque.pop_tail() == one); REQUIRE(*deque.pop_tail() == one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
REQUIRE(*deque.pop_tail() == two); REQUIRE(*deque.pop_tail() == two);
} }
SECTION("remove items form the head") { SECTION("remove items form the head") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
deque.push_tail<int>(no_op, three); deque.push_tail<int>(three);
REQUIRE(*deque.pop_head() == one); REQUIRE(*deque.pop_head() == one);
REQUIRE(*deque.pop_head() == two); REQUIRE(*deque.pop_head() == two);
...@@ -174,47 +173,47 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct ...@@ -174,47 +173,47 @@ TEST_CASE("work stealing deque stores objects correctly", "[internal/data_struct
} }
SECTION("handles getting empty by popping the head correctly") { SECTION("handles getting empty by popping the head correctly") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
REQUIRE(*deque.pop_head() == one); REQUIRE(*deque.pop_head() == one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
REQUIRE(*deque.pop_head() == two); REQUIRE(*deque.pop_head() == two);
} }
SECTION("handles getting empty by popping the head and tail correctly") { SECTION("handles getting empty by popping the head and tail correctly") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
REQUIRE(*deque.pop_tail() == one); REQUIRE(*deque.pop_tail() == one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
REQUIRE(*deque.pop_head() == two); REQUIRE(*deque.pop_head() == two);
deque.push_tail<int>(no_op, three); deque.push_tail<int>(three);
REQUIRE(*deque.pop_tail() == three); REQUIRE(*deque.pop_tail() == three);
} }
SECTION("handles jumps bigger 1 correctly") { SECTION("handles jumps bigger 1 correctly") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
REQUIRE(*deque.pop_tail() == two); REQUIRE(*deque.pop_tail() == two);
deque.push_tail<int>(no_op, three); deque.push_tail<int>(three);
deque.push_tail<int>(no_op, four); deque.push_tail<int>(four);
REQUIRE(*deque.pop_head() == one); REQUIRE(*deque.pop_head() == one);
REQUIRE(*deque.pop_head() == three); REQUIRE(*deque.pop_head() == three);
REQUIRE(*deque.pop_head() == four); REQUIRE(*deque.pop_head() == four);
} }
SECTION("handles stack reset 1 correctly when emptied by tail") { SECTION("handles stack reset 1 correctly when emptied by tail") {
deque.push_tail<int>(no_op, one); deque.push_tail<int>(one);
auto state = deque.save_state(); auto state = deque.save_state();
deque.push_tail<int>(no_op, two); deque.push_tail<int>(two);
REQUIRE(*deque.pop_tail() == two); REQUIRE(*deque.pop_tail() == two);
deque.release_memory_until(state); deque.release_memory_until(state);
REQUIRE(*deque.pop_tail() == one); REQUIRE(*deque.pop_tail() == one);
deque.push_tail<int>(no_op, three); deque.push_tail<int>(three);
deque.push_tail<int>(no_op, four); deque.push_tail<int>(four);
REQUIRE(*deque.pop_head() == three); REQUIRE(*deque.pop_head() == three);
REQUIRE(*deque.pop_tail() == four); REQUIRE(*deque.pop_tail() == four);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment