File indexing completed on 2025-01-18 09:54:52
0001
0002
0003
0004
0005 #ifndef CPPCORO_SINGLE_CONSUMER_EVENT_HPP_INCLUDED
0006 #define CPPCORO_SINGLE_CONSUMER_EVENT_HPP_INCLUDED
0007
0008 #include <atomic>
0009 #include <cppcoro/coroutine.hpp>
0010
0011 namespace cppcoro
0012 {
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025 class single_consumer_event
0026 {
0027 public:
0028
0029
0030
0031
0032
0033
0034
0035 single_consumer_event(bool initiallySet = false) noexcept
0036 : m_state(initiallySet ? state::set : state::not_set)
0037 {}
0038
0039
0040 bool is_set() const noexcept
0041 {
0042 return m_state.load(std::memory_order_acquire) == state::set;
0043 }
0044
0045
0046
0047
0048
0049
0050 void set()
0051 {
0052 const state oldState = m_state.exchange(state::set, std::memory_order_acq_rel);
0053 if (oldState == state::not_set_consumer_waiting)
0054 {
0055 m_awaiter.resume();
0056 }
0057 }
0058
0059
0060
0061 void reset() noexcept
0062 {
0063 state oldState = state::set;
0064 m_state.compare_exchange_strong(oldState, state::not_set, std::memory_order_relaxed);
0065 }
0066
0067
0068
0069
0070
0071
0072
0073
0074 auto operator co_await() noexcept
0075 {
0076 class awaiter
0077 {
0078 public:
0079
0080 awaiter(single_consumer_event& event) : m_event(event) {}
0081
0082 bool await_ready() const noexcept
0083 {
0084 return m_event.is_set();
0085 }
0086
0087 bool await_suspend(cppcoro::coroutine_handle<> awaiter)
0088 {
0089 m_event.m_awaiter = awaiter;
0090
0091 state oldState = state::not_set;
0092 return m_event.m_state.compare_exchange_strong(
0093 oldState,
0094 state::not_set_consumer_waiting,
0095 std::memory_order_release,
0096 std::memory_order_acquire);
0097 }
0098
0099 void await_resume() noexcept {}
0100
0101 private:
0102
0103 single_consumer_event& m_event;
0104
0105 };
0106
0107 return awaiter{ *this };
0108 }
0109
0110 private:
0111
0112 enum class state
0113 {
0114 not_set,
0115 not_set_consumer_waiting,
0116 set
0117 };
0118
0119
0120
0121
0122 std::atomic<state> m_state;
0123 cppcoro::coroutine_handle<> m_awaiter;
0124
0125 };
0126 }
0127
0128 #endif