forked from andreasbuhr/cppcoro
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathasync_manual_reset_event.hpp
More file actions
104 lines (83 loc) · 3.21 KB
/
Copy pathasync_manual_reset_event.hpp
File metadata and controls
104 lines (83 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCORO_ASYNC_MANUAL_RESET_EVENT_HPP_INCLUDED
#define CPPCORO_ASYNC_MANUAL_RESET_EVENT_HPP_INCLUDED
#include <cppcoro/coroutine.hpp>
#include <atomic>
#include <cstdint>
namespace cppcoro
{
class async_manual_reset_event_operation;
/// An async manual-reset event is a coroutine synchronisation abstraction
/// that allows one or more coroutines to wait until some thread calls
/// set() on the event.
///
/// When a coroutine awaits a 'set' event the coroutine continues without
/// suspending. Otherwise, if it awaits a 'not set' event the coroutine is
/// suspended and is later resumed inside the call to 'set()'.
///
/// \seealso async_auto_reset_event
class async_manual_reset_event
{
public:
/// Initialise the event to either 'set' or 'not set' state.
///
/// \param initiallySet
/// If 'true' then initialises the event to the 'set' state, otherwise
/// initialises the event to the 'not set' state.
async_manual_reset_event(bool initiallySet = false) noexcept;
~async_manual_reset_event();
/// Wait for the event to enter the 'set' state.
///
/// If the event is already 'set' then the coroutine continues without
/// suspending.
///
/// Otherwise, the coroutine is suspended and later resumed when some
/// thread calls 'set()'. The coroutine will be resumed inside the next
/// call to 'set()'.
async_manual_reset_event_operation operator co_await() const noexcept;
/// Query if the event is currently in the 'set' state.
bool is_set() const noexcept;
/// Set the state of the event to 'set'.
///
/// If there are pending coroutines awaiting the event then all
/// pending coroutines are resumed within this call.
/// Any coroutines that subsequently await the event will continue
/// without suspending.
///
/// This operation is a no-op if the event was already 'set'.
void set() noexcept;
/// Set the state of the event to 'not-set'.
///
/// Any coroutines that subsequently await the event will suspend
/// until some thread calls 'set()'.
///
/// This is a no-op if the state was already 'not set'.
void reset() noexcept;
private:
friend class async_manual_reset_event_operation;
// This variable has 3 states:
// - this - The state is 'set'.
// - nullptr - The state is 'not set' with no waiters.
// - other - The state is 'not set'.
// Points to an 'async_manual_reset_event_operation' that is
// the head of a linked-list of waiters.
mutable std::atomic<void*> m_state;
};
class async_manual_reset_event_operation
{
public:
explicit async_manual_reset_event_operation(const async_manual_reset_event& event) noexcept;
bool await_ready() const noexcept;
bool await_suspend(cppcoro::coroutine_handle<> awaiter) noexcept;
void await_resume() const noexcept {}
private:
friend class async_manual_reset_event;
const async_manual_reset_event& m_event;
async_manual_reset_event_operation* m_next;
cppcoro::coroutine_handle<> m_awaiter;
};
}
#endif