66
77#include < concepts>
88#include < coroutine>
9+ #include < memory>
910#include < utility>
1011
12+ #include " common/mixin/not_copyable.h"
13+ #include " runtime-common/core/allocator/script-allocator-managed.h"
1114#include " runtime-light/coroutine/async-stack.h"
1215#include " runtime-light/coroutine/coroutine-state.h"
1316#include " runtime-light/stdlib/diagnostics/logs.h"
1417
1518namespace kphp ::coro {
1619
1720class event {
18- // 1) nullptr => not set
19- // 2) awaiter* => linked list of awaiters waiting for the event to trigger
20- // 3) this => The event is triggered and all awaiters are resumed
21- void * m_state{};
21+ struct event_controller : kphp::memory::script_allocator_managed, vk::not_copyable {
22+ // 1) nullptr => not set
23+ // 2) awaiter* => linked list of awaiters waiting for the event to trigger
24+ // 3) this => The event is triggered and all awaiters are resumed
25+ void * m_state{};
26+
27+ auto set () noexcept -> void;
28+ auto unset () noexcept -> void;
29+ auto is_set () const noexcept -> bool;
30+ };
31+
32+ std::unique_ptr<event_controller> m_controller;
2233
2334 struct awaiter {
24- event& m_event;
2535 bool m_suspended{};
36+ event_controller& m_controller;
2637 std::coroutine_handle<> m_awaiting_coroutine;
2738 kphp::coro::async_stack_root& m_async_stack_root;
2839 kphp::coro::async_stack_frame* m_caller_async_stack_frame{};
2940
3041 awaiter* m_next{};
3142 awaiter* m_prev{};
3243
33- explicit awaiter (event& event ) noexcept
34- : m_event(event ),
44+ explicit awaiter (event_controller& event_controller ) noexcept
45+ : m_controller(event_controller ),
3546 m_async_stack_root(CoroutineInstanceState::get().coroutine_stack_root) {}
3647
3748 awaiter (const awaiter&) = delete ;
@@ -55,10 +66,28 @@ class event {
5566 };
5667
5768public:
58- auto set () noexcept -> void;
69+ event () noexcept
70+ : m_controller(std::make_unique<event_controller>()) {
71+ kphp::log::assertion (m_controller != nullptr );
72+ }
5973
60- auto unset () noexcept -> void;
74+ event (event&& other) noexcept
75+ : m_controller(std::move(other.m_controller)) {}
76+
77+ event& operator =(event&& other) noexcept {
78+ if (this != std::addressof (other)) {
79+ m_controller = std::move (other.m_controller );
80+ }
81+ return *this ;
82+ }
83+
84+ ~event () = default ;
6185
86+ event (const event&) = delete ;
87+ event& operator =(const event&) = delete ;
88+
89+ auto set () noexcept -> void;
90+ auto unset () noexcept -> void;
6291 auto is_set () const noexcept -> bool;
6392
6493 auto operator co_await () noexcept ;
@@ -72,14 +101,14 @@ inline auto event::awaiter::cancel_awaiter() noexcept -> void {
72101 m_prev->m_next = m_next;
73102 } else {
74103 // we are the head of the awaiters list, so we need to update the head
75- m_event .m_state = m_next;
104+ m_controller .m_state = m_next;
76105 }
77106 m_next = nullptr ;
78107 m_prev = nullptr ;
79108}
80109
81110inline auto event::awaiter::await_ready () const noexcept -> bool {
82- return m_event .is_set ();
111+ return m_controller .is_set ();
83112}
84113
85114template <std::derived_from<kphp::coro::async_stack_element> caller_promise_type>
@@ -90,15 +119,15 @@ auto event::awaiter::await_suspend(std::coroutine_handle<caller_promise_type> aw
90119 m_suspended = true ;
91120 m_awaiting_coroutine = awaiting_coroutine;
92121
93- m_next = static_cast <event::awaiter*>(m_event .m_state );
122+ m_next = static_cast <event::awaiter*>(m_controller .m_state );
94123
95124 // ensure that the event isn't triggered
96- kphp::log::assertion (reinterpret_cast <event *>(m_next) != std::addressof (m_event ));
125+ kphp::log::assertion (reinterpret_cast <event_controller *>(m_next) != std::addressof (m_controller ));
97126
98127 if (m_next != nullptr ) {
99128 m_next->m_prev = this ;
100129 }
101- m_event .m_state = this ;
130+ m_controller .m_state = this ;
102131}
103132
104133inline auto event::awaiter::await_resume () noexcept -> void {
@@ -109,7 +138,7 @@ inline auto event::awaiter::await_resume() noexcept -> void {
109138 }
110139}
111140
112- inline auto event::set () noexcept -> void {
141+ inline auto event::event_controller:: set () noexcept -> void {
113142 void * prev_value{std::exchange (m_state, this )};
114143 if (prev_value == this || prev_value == nullptr ) [[unlikely]] {
115144 return ;
@@ -122,18 +151,34 @@ inline auto event::set() noexcept -> void {
122151 }
123152}
124153
125- inline auto event::unset () noexcept -> void {
154+ inline auto event::event_controller:: unset () noexcept -> void {
126155 if (m_state == this ) {
127156 m_state = nullptr ;
128157 }
129158}
130159
131- inline auto event::is_set () const noexcept -> bool {
160+ inline auto event::event_controller:: is_set () const noexcept -> bool {
132161 return m_state == this ;
133162}
134163
164+ inline auto event::set () noexcept -> void {
165+ kphp::log::assertion (m_controller != nullptr );
166+ m_controller->set ();
167+ }
168+
169+ inline auto event::unset () noexcept -> void {
170+ kphp::log::assertion (m_controller != nullptr );
171+ m_controller->unset ();
172+ }
173+
174+ inline auto event::is_set () const noexcept -> bool {
175+ kphp::log::assertion (m_controller != nullptr );
176+ return m_controller->is_set ();
177+ }
178+
135179inline auto event::operator co_await () noexcept {
136- return event::awaiter{*this };
180+ kphp::log::assertion (m_controller != nullptr );
181+ return event::awaiter{*this ->m_controller };
137182}
138183
139184} // namespace kphp::coro
0 commit comments