#include #include #include "pls/internal/scheduling/traded_cas_field.h" #include "pls/internal/scheduling/task.h" #include "pls/internal/scheduling/external_trading_deque.h" using namespace pls::internal::scheduling; TEST_CASE("traded cas field bitmaps correctly", "[internal/scheduling/traded_cas_field.h]") { traded_cas_field empty_field; REQUIRE(empty_field.is_empty()); REQUIRE(!empty_field.is_filled_with_stamp()); REQUIRE(!empty_field.is_filled_with_object()); const int stamp = 42; const int ID = 10; traded_cas_field tag_field; tag_field.fill_with_stamp(stamp, ID); REQUIRE(tag_field.is_filled_with_stamp()); REQUIRE(!tag_field.is_empty()); REQUIRE(!tag_field.is_filled_with_object()); REQUIRE(tag_field.get_stamp() == stamp); REQUIRE(tag_field.get_deque_id() == ID); alignas(64) task obj; traded_cas_field obj_field; obj_field.fill_with_trade_object(&obj); REQUIRE(obj_field.is_filled_with_object()); REQUIRE(!obj_field.is_empty()); REQUIRE(!obj_field.is_filled_with_stamp()); } TEST_CASE("external trading deque", "[internal/scheduling/external_trading_deque]") { static_external_trading_deque<16> static_external_trading_deque_1; external_trading_deque &deque_1 = static_external_trading_deque_1.get_deque(); deque_1.set_thread_id(1); static_external_trading_deque<16> static_external_trading_deque_2; external_trading_deque &deque_2 = static_external_trading_deque_2.get_deque(); deque_2.set_thread_id(2); std::vector tasks(16); SECTION("basic operations") { // Must start empty REQUIRE(!deque_1.pop_bot()); REQUIRE(!deque_2.pop_bot()); // Local push/pop deque_1.push_bot(&tasks[0]); REQUIRE(*deque_1.pop_bot() == &tasks[0]); REQUIRE(!deque_1.pop_bot()); // Local push, external pop deque_1.push_bot(&tasks[0]); auto peek = deque_1.peek_top(); REQUIRE(*deque_1.pop_top(&tasks[1], peek.top_pointer_) == &tasks[0]); REQUIRE(*external_trading_deque::get_trade_object(&tasks[0]) == &tasks[1]); REQUIRE(!deque_1.pop_top(&tasks[1], peek.top_pointer_)); REQUIRE(!deque_1.pop_bot()); // Keeps push/pop order deque_1.push_bot(&tasks[0]); deque_1.push_bot(&tasks[1]); REQUIRE(*deque_1.pop_bot() == &tasks[1]); REQUIRE(*deque_1.pop_bot() == &tasks[0]); REQUIRE(!deque_1.pop_bot()); deque_1.push_bot(&tasks[0]); deque_1.push_bot(&tasks[1]); auto peek1 = deque_1.peek_top(); REQUIRE(*deque_1.pop_top(&tasks[2], peek1.top_pointer_) == &tasks[0]); auto peek2 = deque_1.peek_top(); REQUIRE(*deque_1.pop_top(&tasks[3], peek2.top_pointer_) == &tasks[1]); } SECTION("Interwined execution #1") { // Two top poppers deque_1.push_bot(&tasks[0]); auto peek1 = deque_1.peek_top(); auto peek2 = deque_1.peek_top(); REQUIRE(*deque_1.pop_top(&tasks[1], peek1.top_pointer_) == &tasks[0]); REQUIRE(!deque_1.pop_top(&tasks[2], peek2.top_pointer_)); } SECTION("Interwined execution #2") { // Top and bottom access deque_1.push_bot(&tasks[0]); auto peek1 = deque_1.peek_top(); REQUIRE(*deque_1.pop_bot() == &tasks[0]); REQUIRE(!deque_1.pop_top(&tasks[2], peek1.top_pointer_)); } }