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_MANUAL_RESET_EVENT_HPP_INCLUDED
0006 #define CPPCORO_ASYNC_MANUAL_RESET_EVENT_HPP_INCLUDED
0007 
0008 #include <cppcoro/coroutine.hpp>
0009 #include <atomic>
0010 #include <cstdint>
0011 
0012 namespace cppcoro
0013 {
0014     class async_manual_reset_event_operation;
0015 
0016     /// An async manual-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 coroutine continues without
0021     /// suspending. Otherwise, if it awaits a 'not set' event the coroutine is
0022     /// suspended and is later resumed inside the call to 'set()'.
0023     ///
0024     /// \seealso async_auto_reset_event
0025     class async_manual_reset_event
0026     {
0027     public:
0028 
0029         /// Initialise the event to either 'set' or 'not set' state.
0030         ///
0031         /// \param initiallySet
0032         /// If 'true' then initialises the event to the 'set' state, otherwise
0033         /// initialises the event to the 'not set' state.
0034         async_manual_reset_event(bool initiallySet = false) noexcept;
0035 
0036         ~async_manual_reset_event();
0037 
0038         /// Wait for the event to enter the 'set' state.
0039         ///
0040         /// If the event is already 'set' then the coroutine continues without
0041         /// suspending.
0042         ///
0043         /// Otherwise, the coroutine is suspended and later resumed when some
0044         /// thread calls 'set()'. The coroutine will be resumed inside the next
0045         /// call to 'set()'.
0046         async_manual_reset_event_operation operator co_await() const noexcept;
0047 
0048         /// Query if the event is currently in the 'set' state.
0049         bool is_set() const noexcept;
0050 
0051         /// Set the state of the event to 'set'.
0052         ///
0053         /// If there are pending coroutines awaiting the event then all
0054         /// pending coroutines are resumed within this call.
0055         /// Any coroutines that subsequently await the event will continue
0056         /// without suspending.
0057         ///
0058         /// This operation is a no-op if the event was already 'set'.
0059         void set() noexcept;
0060 
0061         /// Set the state of the event to 'not-set'.
0062         ///
0063         /// Any coroutines that subsequently await the event will suspend
0064         /// until some thread calls 'set()'.
0065         ///
0066         /// This is a no-op if the state was already 'not set'.
0067         void reset() noexcept;
0068 
0069     private:
0070 
0071         friend class async_manual_reset_event_operation;
0072 
0073         // This variable has 3 states:
0074         // - this    - The state is 'set'.
0075         // - nullptr - The state is 'not set' with no waiters.
0076         // - other   - The state is 'not set'.
0077         //             Points to an 'async_manual_reset_event_operation' that is
0078         //             the head of a linked-list of waiters.
0079         mutable std::atomic<void*> m_state;
0080 
0081     };
0082 
0083     class async_manual_reset_event_operation
0084     {
0085     public:
0086 
0087         explicit async_manual_reset_event_operation(const async_manual_reset_event& event) noexcept;
0088 
0089         bool await_ready() const noexcept;
0090         bool await_suspend(cppcoro::coroutine_handle<> awaiter) noexcept;
0091         void await_resume() const noexcept {}
0092 
0093     private:
0094 
0095         friend class async_manual_reset_event;
0096 
0097         const async_manual_reset_event& m_event;
0098         async_manual_reset_event_operation* m_next;
0099         cppcoro::coroutine_handle<> m_awaiter;
0100 
0101     };
0102 }
0103 
0104 #endif