3#include <asyncpp/dispatcher.h>
38 : m_state(set_initially ? this :
nullptr) {}
46 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
53 auto val = m_state.load(std::memory_order::acquire);
54 return val !=
nullptr && val !=
this;
64 auto state = m_state.exchange(
this, std::memory_order::acq_rel);
65 if (state !=
nullptr && state !=
this) {
66 auto await =
static_cast<awaiter*
>(state);
67 assert(await->m_parent ==
this);
68 assert(await->m_handle);
69 if (await->m_dispatcher !=
nullptr) {
70 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
71 }
else if (resume_dispatcher !=
nullptr) {
72 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
74 await->m_handle.resume();
85 void* old_state =
this;
86 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
109 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
110 return awaiter{
this, resume_dispatcher};
118 std::atomic<void*> m_state;
120 struct [[nodiscard]] awaiter {
122 : m_parent(parent), m_dispatcher(
dispatcher) {}
123 [[nodiscard]]
bool await_ready() const noexcept {
return m_parent->is_set(); }
124 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
126 void* old_state =
nullptr;
128 bool was_equal = m_parent->m_state.compare_exchange_strong(old_state,
this, std::memory_order::release,
129 std::memory_order::acquire);
132 assert(was_equal || old_state == m_parent);
135 constexpr void await_resume() const noexcept {}
137 single_consumer_event* m_parent;
138 dispatcher* m_dispatcher;
139 coroutine_handle<> m_handle{};
174 : m_state(set_initially ? this :
nullptr) {}
182 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
189 auto ptr = m_state.load(std::memory_order::acquire);
190 return ptr !=
nullptr && ptr !=
this;
200 auto state = m_state.exchange(
this, std::memory_order::release);
201 if (state !=
nullptr && state !=
this) {
202 auto await =
static_cast<awaiter*
>(state);
206 m_state.compare_exchange_strong(state,
nullptr, std::memory_order::acq_rel);
208 assert(await->m_parent ==
this);
209 assert(await->m_handle);
210 if (await->m_dispatcher !=
nullptr) {
211 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
212 }
else if (resume_dispatcher !=
nullptr) {
213 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
215 await->m_handle.resume();
226 void* old_state =
this;
227 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
250 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
251 return awaiter{
this, resume_dispatcher};
259 std::atomic<void*> m_state;
261 struct [[nodiscard]] awaiter {
263 : m_parent(parent), m_dispatcher(
dispatcher) {}
264 [[nodiscard]]
constexpr bool await_ready() const noexcept {
return false; }
265 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
267 void* old_state =
nullptr;
268 if (!m_parent->m_state.compare_exchange_strong(old_state,
this, std::memory_order::release,
269 std::memory_order::relaxed)) {
271 assert(m_parent == old_state);
272 m_parent->m_state.exchange(
nullptr, std::memory_order::acquire);
277 constexpr void await_resume() const noexcept {}
279 single_consumer_auto_reset_event* m_parent;
280 dispatcher* m_dispatcher;
281 coroutine_handle<> m_handle{};
314 : m_state(set_initially ? this :
nullptr) {}
323 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
330 auto ptr = m_state.load(std::memory_order::acquire);
331 return ptr !=
nullptr && ptr !=
this;
341 auto state = m_state.exchange(
this, std::memory_order::acq_rel);
342 if (state ==
this)
return false;
343 auto await =
static_cast<awaiter*
>(state);
344 while (await !=
nullptr) {
345 auto next = await->m_next;
346 assert(await->m_parent ==
this);
347 assert(await->m_handle);
348 if (await->m_dispatcher !=
nullptr) {
349 await->m_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
350 }
else if (resume_dispatcher !=
nullptr) {
351 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
353 await->m_handle.resume();
364 void* old_state =
this;
365 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
388 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
389 return awaiter{
this, resume_dispatcher};
397 std::atomic<void*> m_state;
399 struct [[nodiscard]] awaiter {
401 : m_parent(parent), m_dispatcher(
dispatcher) {}
402 [[nodiscard]]
bool await_ready() const noexcept {
return m_parent->is_set(); }
403 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
405 void* old_state = m_parent->m_state.load(std::memory_order::acquire);
408 if (old_state == m_parent)
return false;
409 m_next =
static_cast<awaiter*
>(old_state);
410 }
while (!m_parent->m_state.compare_exchange_weak(
411 old_state,
this, std::memory_order::release, std::memory_order::acquire));
414 constexpr void await_resume() const noexcept {}
416 multi_consumer_event* m_parent;
417 dispatcher* m_dispatcher;
418 awaiter* m_next{
nullptr};
419 coroutine_handle<> m_handle{};
454 : m_state(set_initially ? this :
nullptr) {}
463 [[nodiscard]]
bool is_set() const noexcept {
return m_state.load(std::memory_order::acquire) ==
this; }
470 auto ptr = m_state.load(std::memory_order::acquire);
471 return ptr !=
nullptr && ptr !=
this;
482 awaiter* await =
nullptr;
483 void* old_state = m_state.load(std::memory_order::acquire);
487 if (old_state ==
this)
return false;
489 await =
static_cast<awaiter*
>(old_state);
491 new_state = (old_state ==
nullptr) ?
this :
nullptr;
492 }
while (!m_state.compare_exchange_weak(old_state, new_state, std::memory_order::release,
493 std::memory_order::acquire));
496 if (await ==
nullptr)
return false;
498 auto next = await->m_next;
499 assert(await->m_parent ==
this);
500 assert(await->m_handle);
501 if (await->m_dispatcher !=
nullptr) {
502 await->m_dispatcher->
push([hdl = await->m_handle]()
mutable { hdl.resume(); });
503 }
else if (resume_dispatcher !=
nullptr) {
504 resume_dispatcher->push([hdl = await->m_handle]()
mutable { hdl.resume(); });
506 await->m_handle.resume();
509 }
while (await !=
nullptr);
517 void* old_state =
this;
518 m_state.compare_exchange_strong(old_state,
nullptr, std::memory_order::relaxed);
541 [[nodiscard]]
constexpr auto wait(
dispatcher* resume_dispatcher =
nullptr) noexcept {
542 return awaiter{
this, resume_dispatcher};
550 std::atomic<void*> m_state;
552 struct [[nodiscard]] awaiter {
554 : m_parent(parent), m_dispatcher(
dispatcher) {}
555 [[nodiscard]]
bool await_ready() const noexcept {
557 void* old_state = m_parent;
562 return m_parent->m_state.compare_exchange_weak(
563 old_state,
nullptr, std::memory_order::release, std::memory_order::acquire);
565 [[nodiscard]]
bool await_suspend(coroutine_handle<> hdl)
noexcept {
567 void* old_state = m_parent->m_state.load(std::memory_order::acquire);
570 if (old_state == m_parent) {
571 if (m_parent->m_state.compare_exchange_weak(
572 old_state,
nullptr, std::memory_order::release, std::memory_order::acquire))
579 m_next =
static_cast<awaiter*
>(old_state);
580 }
while (!m_parent->m_state.compare_exchange_weak(
581 old_state,
this, std::memory_order::release, std::memory_order::acquire));
584 constexpr void await_resume() const noexcept {}
586 multi_consumer_auto_reset_event* m_parent;
587 dispatcher* m_dispatcher{};
588 awaiter* m_next{
nullptr};
589 coroutine_handle<> m_handle{};
Basic dispatcher interface class.
Definition dispatcher.h:8
static dispatcher * current() noexcept
Definition dispatcher.h:48
virtual void push(std::function< void()> cbfn)=0
Simple auto reset event supporting multiple consumers.
Definition event.h:447
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:541
constexpr multi_consumer_auto_reset_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:453
void reset() noexcept
Reset the event back to unset.
Definition event.h:516
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:480
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:463
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:469
Simple manual reset event supporting multiple consumers.
Definition event.h:307
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:329
void reset() noexcept
Reset the event back to unset.
Definition event.h:363
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:340
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:323
constexpr multi_consumer_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:313
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:388
Simple auto reset event supporting a single consumer.
Definition event.h:167
void reset() noexcept
Reset the event back to unset.
Definition event.h:225
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:182
constexpr single_consumer_auto_reset_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:173
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:250
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:188
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:199
Simple manual reset event supporting a single consumer.
Definition event.h:31
bool is_set() const noexcept
Query if the event is currently set.
Definition event.h:46
bool set(dispatcher *resume_dispatcher=nullptr) noexcept
Set the event.
Definition event.h:63
bool is_awaited() const noexcept
Query if the event is currently being awaited.
Definition event.h:52
void reset() noexcept
Reset the event back to unset.
Definition event.h:84
constexpr single_consumer_event(bool set_initially=false) noexcept
Construct a new event.
Definition event.h:37
constexpr auto wait(dispatcher *resume_dispatcher=nullptr) noexcept
Suspend the current coroutine until the event is set.
Definition event.h:109
Provides a consistent import interface for coroutine, experimental/coroutine or a best effort fallbac...