Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:54:51

0001 ///////////////////////////////////////////////////////////////////////////////
0002 // Copyright (c) Lewis Baker
0003 // Licenced under MIT license. See LICENSE.txt for details.
0004 ///////////////////////////////////////////////////////////////////////////////
0005 #ifndef CPPCORO_ASYNC_AUTO_RESET_EVENT_HPP_INCLUDED
0006 #define CPPCORO_ASYNC_AUTO_RESET_EVENT_HPP_INCLUDED
0007 
0008 #include <cppcoro/coroutine.hpp>
0009 #include <atomic>
0010 #include <cstdint>
0011 
0012 namespace cppcoro
0013 {
0014     class async_auto_reset_event_operation;
0015 
0016     /// An async auto-reset event is a coroutine synchronisation abstraction
0017     /// that allows one or more coroutines to wait until some thread calls
0018     /// set() on the event.
0019     ///
0020     /// When a coroutine awaits a 'set' event the event is automatically
0021     /// reset back to the 'not set' state, thus the name 'auto reset' event.
0022     class async_auto_reset_event
0023     {
0024     public:
0025 
0026         /// Initialise the event to either 'set' or 'not set' state.
0027         async_auto_reset_event(bool initiallySet = false) noexcept;
0028 
0029         ~async_auto_reset_event();
0030 
0031         /// Wait for the event to enter the 'set' state.
0032         ///
0033         /// If the event is already 'set' then the event is set to the 'not set'
0034         /// state and the awaiting coroutine continues without suspending.
0035         /// Otherwise, the coroutine is suspended and later resumed when some
0036         /// thread calls 'set()'.
0037         ///
0038         /// Note that the coroutine may be resumed inside a call to 'set()'
0039         /// or inside another thread's call to 'operator co_await()'.
0040         async_auto_reset_event_operation operator co_await() const noexcept;
0041 
0042         /// Set the state of the event to 'set'.
0043         ///
0044         /// If there are pending coroutines awaiting the event then one
0045         /// pending coroutine is resumed and the state is immediately
0046         /// set back to the 'not set' state.
0047         ///
0048         /// This operation is a no-op if the event was already 'set'.
0049         void set() noexcept;
0050 
0051         /// Set the state of the event to 'not-set'.
0052         ///
0053         /// This is a no-op if the state was already 'not set'.
0054         void reset() noexcept;
0055 
0056     private:
0057 
0058         friend class async_auto_reset_event_operation;
0059 
0060         void resume_waiters(std::uint64_t initialState) const noexcept;
0061 
0062         // Bits 0-31  - Set count
0063         // Bits 32-63 - Waiter count
0064         mutable std::atomic<std::uint64_t> m_state;
0065 
0066         mutable std::atomic<async_auto_reset_event_operation*> m_newWaiters;
0067 
0068         mutable async_auto_reset_event_operation* m_waiters;
0069 
0070     };
0071 
0072     class async_auto_reset_event_operation
0073     {
0074     public:
0075 
0076         async_auto_reset_event_operation() noexcept;
0077 
0078         explicit async_auto_reset_event_operation(const async_auto_reset_event& event) noexcept;
0079 
0080         async_auto_reset_event_operation(const async_auto_reset_event_operation& other) noexcept;
0081 
0082         bool await_ready() const noexcept { return m_event == nullptr; }
0083         bool await_suspend(cppcoro::coroutine_handle<> awaiter) noexcept;
0084         void await_resume() const noexcept {}
0085 
0086     private:
0087 
0088         friend class async_auto_reset_event;
0089 
0090         const async_auto_reset_event* m_event;
0091         async_auto_reset_event_operation* m_next;
0092         cppcoro::coroutine_handle<> m_awaiter;
0093         std::atomic<std::uint32_t> m_refCount;
0094 
0095     };
0096 }
0097 
0098 #endif