3#include <asyncpp/dispatcher.h>
37 : m_state(set_initially ? this :
nullptr) {}
45 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
52 auto val = m_state.load(std::memory_order::acquire);
53 return val !=
nullptr && val !=
this;
63 auto state = m_state.exchange(
this, std::memory_order::acq_rel);
64 if (state !=
nullptr && state !=
this) {
65 auto await =
static_cast<awaiter*
>(state);
66 assert(await->m_parent ==
this);
67 assert(await->m_handle);
68 if (await->m_dispatcher !=
nullptr) {
69 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
70 }
else if (resume_dispatcher !=
nullptr) {
71 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
73 await->m_handle.resume();
84 void* old_state =
this;
85 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
108 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
109 return awaiter{
this, resume_dispatcher};
117 std::atomic<void*> m_state;
119 struct [[nodiscard]] awaiter {
121 : m_parent(parent), m_dispatcher(
dispatcher) {}
122 [[nodiscard]]
bool await_ready() const noexcept {
return m_parent->is_set(); }
123 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
125 void* old_state =
nullptr;
127 bool was_equal = m_parent->m_state.compare_exchange_strong(old_state,
this, std::memory_order::release,
128 std::memory_order::acquire);
131 assert(was_equal || old_state == m_parent);
134 constexpr void await_resume() const noexcept {}
136 single_consumer_event* m_parent;
137 dispatcher* m_dispatcher;
138 coroutine_handle<> m_handle{};
173 : m_state(set_initially ? this :
nullptr) {}
181 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
188 auto ptr = m_state.load(std::memory_order::acquire);
189 return ptr !=
nullptr && ptr !=
this;
199 auto state = m_state.exchange(
this, std::memory_order::release);
200 if (state !=
nullptr && state !=
this) {
201 auto await =
static_cast<awaiter*
>(state);
205 m_state.compare_exchange_strong(state,
nullptr, std::memory_order::acq_rel);
207 assert(await->m_parent ==
this);
208 assert(await->m_handle);
209 if (await->m_dispatcher !=
nullptr) {
210 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
211 }
else if (resume_dispatcher !=
nullptr) {
212 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
214 await->m_handle.resume();
225 void* old_state =
this;
226 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
249 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
250 return awaiter{
this, resume_dispatcher};
258 std::atomic<void*> m_state;
260 struct [[nodiscard]] awaiter {
262 : m_parent(parent), m_dispatcher(
dispatcher) {}
263 [[nodiscard]]
constexpr bool await_ready() const noexcept {
return false; }
264 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
266 void* old_state =
nullptr;
267 if (!m_parent->m_state.compare_exchange_strong(old_state,
this, std::memory_order::release,
268 std::memory_order::relaxed)) {
270 assert(m_parent == old_state);
271 m_parent->m_state.exchange(
nullptr, std::memory_order::acquire);
276 constexpr void await_resume() const noexcept {}
278 single_consumer_auto_reset_event* m_parent;
279 dispatcher* m_dispatcher;
280 coroutine_handle<> m_handle{};
313 : m_state(set_initially ? this :
nullptr) {}
322 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
329 auto ptr = m_state.load(std::memory_order::acquire);
330 return ptr !=
nullptr && ptr !=
this;
340 auto state = m_state.exchange(
this, std::memory_order::acq_rel);
341 if (state ==
this)
return false;
342 auto await =
static_cast<awaiter*
>(state);
343 while (await !=
nullptr) {
344 auto next = await->m_next;
345 assert(await->m_parent ==
this);
346 assert(await->m_handle);
347 if (await->m_dispatcher !=
nullptr) {
348 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
349 }
else if (resume_dispatcher !=
nullptr) {
350 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
352 await->m_handle.resume();
363 void* old_state =
this;
364 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
387 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
388 return awaiter{
this, resume_dispatcher};
396 std::atomic<void*> m_state;
398 struct [[nodiscard]] awaiter {
400 : m_parent(parent), m_dispatcher(
dispatcher) {}
401 [[nodiscard]]
bool await_ready() const noexcept {
return m_parent->is_set(); }
402 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
404 void* old_state = m_parent->m_state.load(std::memory_order::acquire);
407 if (old_state == m_parent)
return false;
408 m_next =
static_cast<awaiter*
>(old_state);
409 }
while (!m_parent->m_state.compare_exchange_weak(
410 old_state,
this, std::memory_order::release, std::memory_order::acquire));
413 constexpr void await_resume() const noexcept {}
415 multi_consumer_event* m_parent;
416 dispatcher* m_dispatcher;
417 awaiter* m_next{
nullptr};
418 coroutine_handle<> m_handle{};
452 : m_state(set_initially ?
this :
nullptr) {}
461 [[nodiscard]]
bool is_set()
const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
467 [[nodiscard]]
bool is_awaited()
const noexcept {
468 auto ptr = m_state.load(std::memory_order::acquire);
469 return ptr !=
nullptr && ptr !=
this;
478 bool set(
dispatcher* resume_dispatcher =
nullptr)
noexcept {
479 auto state = m_state.exchange(
this, std::memory_order::acq_rel);
480 if (state ==
this || state ==
nullptr)
return false;
481 auto await =
static_cast<awaiter*
>(state);
485 m_state.compare_exchange_strong(state,
nullptr, std::memory_order::acq_rel);
487 while (await !=
nullptr) {
488 auto next = await->m_next;
489 assert(await->m_parent ==
this);
490 assert(await->m_handle);
491 if (await->m_dispatcher !=
nullptr) {
492 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
493 }
else if (resume_dispatcher !=
nullptr) {
494 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
496 await->m_handle.resume();
506 void reset()
noexcept {
507 void* old_state =
this;
508 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
519 [[nodiscard]]
auto operator co_await()
noexcept {
return awaiter{
this,
dispatcher::current()}; }
531 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr)
noexcept {
532 return awaiter{
this, resume_dispatcher};
540 std::atomic<void*> m_state;
542 struct [[nodiscard]] awaiter {
544 : m_parent(parent), m_dispatcher(
dispatcher) {}
545 [[nodiscard]]
bool await_ready()
const noexcept {
return m_parent->is_set(); }
546 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
548 void* old_state = m_parent->m_state.load(std::memory_order::acquire);
551 if (old_state == m_parent)
return false;
552 m_next =
static_cast<awaiter*
>(old_state);
553 }
while (!m_parent->m_state.compare_exchange_weak(
554 old_state,
this, std::memory_order::release, std::memory_order::acquire));
557 constexpr void await_resume()
const noexcept {}
561 awaiter* m_next{
nullptr};
562 coroutine_handle<> m_handle{};
Basic dispatcher interface class.
Definition dispatcher.h:8
static dispatcher * current() noexcept
Definition dispatcher.h:48
Simple auto reset event supporting multiple consumers.
Definition event.h:446
Simple manual reset event supporting multiple consumers.
Definition event.h:306
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:328
void reset() noexcept
Reset the event back to unset.
Definition event.h:362
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:339
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:322
constexpr multi_consumer_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:312
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:387
Simple auto reset event supporting a single consumer.
Definition event.h:166
void reset() noexcept
Reset the event back to unset.
Definition event.h:224
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:181
constexpr single_consumer_auto_reset_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:172
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:249
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:187
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:198
Simple manual reset event supporting a single consumer.
Definition event.h:30
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:45
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:62
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:51
void reset() noexcept
Reset the event back to unset.
Definition event.h:83
constexpr single_consumer_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:36
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:108
Provides a consistent import interface for coroutine, experimental/coroutine or a best effort fallbac...