48 static constexpr auto phase_alignment = phase_ref_t::required_alignment;
56 struct alignas(64) state_data {
57 alignas(phase_alignment) array<byte_t, 64> tickets;
63 CmplFunc completion_function_;
64 alignas(phase_alignment)
byte_t current_phase_;
74 bool do_arrive(
const byte_t old_phase,
size_t current_index) {
75 const auto old_phase_value = old_phase;
76 const auto half_step =
static_cast<byte_t>(old_phase_value + 1);
77 const auto full_step =
static_cast<byte_t>(old_phase_value + 2);
79 size_t current_expected = expected_count_;
80 current_index %= ((expected_count_ + 1) >> 1);
83 if (current_expected <= 1)
86 size_t const end_node =
87 ((current_expected + 1) >> 1),
88 last_node = end_node - 1;
90 for ( ; ; ++current_index) {
91 if (current_index == end_node)
94 auto expected_phase = old_phase;
95 phase_ref_t phase_ref(state_array_[current_index].tickets[
round]);
97 if (current_index == last_node && (current_expected & 1)) {
98 if (phase_ref.compare_exchange_strong(
102 }
else if (phase_ref.compare_exchange_strong(
105 }
else if (expected_phase == half_step) {
106 if (phase_ref.compare_exchange_strong(
113 current_expected = last_node + 1;
135 : expected_count_(expected),
136 expected_adjustment_(0),
137 completion_function_(
_MSTL move(completion)),
138 current_phase_(static_cast<
byte_t>(0)) {
139 size_t const count = (expected_count_ + 1) >> 1;
153 const size_t current_index = hasher(this_thread::id());
154 phase_ref_t phase_ref(current_phase_);
156 const auto current_phase_value =
static_cast<byte_t>(old_phase);
158 for(; update; --update) {
159 if(do_arrive(old_phase, current_index)) {
160 completion_function_();
163 const auto new_phase =
static_cast<byte_t>(current_phase_value + 2);
165 phase_ref.notify_all();
178 phase_cref_t phase_ref(current_phase_);
179 auto const test_function = [=] {
192 static_cast<void>(
arrive(1));