11namespace Lightweight::Async
31 void SetWaker(std::function<
void()> waker)
33 _waker = std::move(waker);
38 _set.store(
true, std::memory_order_release);
49 [[nodiscard]]
bool IsSet() const noexcept
51 return _set.load(std::memory_order_acquire);
55 std::atomic<bool> _set {
false };
56 std::binary_semaphore _semaphore { 0 };
57 std::function<void()> _waker;
66 struct SyncWaitFinalAwaiter
68 [[nodiscard]]
bool await_ready() const noexcept
72 template <
typename Promise>
73 void await_suspend(std::coroutine_handle<Promise> coro)
const noexcept
75 coro.promise().Signal();
77 void await_resume() const noexcept {}
86 class SyncWaitPromiseBase
89 std::suspend_always initial_suspend() noexcept
94 SyncWaitFinalAwaiter final_suspend() noexcept
99 void Bind(SyncWaitEvent& signal)
noexcept
104 void Signal() const noexcept
110 SyncWaitEvent* _event =
nullptr;
114 template <
typename T>
115 class SyncWaitPromise final:
public SyncWaitPromiseBase
118 SyncWaitTask<T> get_return_object() noexcept;
120 void unhandled_exception() noexcept
122 _result.SetException();
125 void return_value(T&& value)
noexcept(std::is_nothrow_move_constructible_v<T>)
127 _result.SetValue(std::move(value));
130 void return_value(T
const& value)
132 _result.SetValue(value);
135 [[nodiscard]] T Take()
137 return _result.Take();
141 CoroutineResult<T> _result;
145 class SyncWaitPromise<void> final:
public SyncWaitPromiseBase
148 SyncWaitTask<void> get_return_object() noexcept;
150 void unhandled_exception() noexcept
152 _result.SetException();
155 void return_void() noexcept {}
163 CoroutineResult<void> _result;
167 template <
typename T>
171 using promise_type = SyncWaitPromise<T>;
172 using Handle = std::coroutine_handle<promise_type>;
174 explicit SyncWaitTask(Handle handle)
noexcept:
179 SyncWaitTask(SyncWaitTask&& other)
noexcept:
180 _handle { std::exchange(other._handle, {}) }
184 SyncWaitTask(SyncWaitTask
const&) =
delete;
185 SyncWaitTask& operator=(SyncWaitTask
const&) =
delete;
186 SyncWaitTask& operator=(SyncWaitTask&&) =
delete;
194 void Start(SyncWaitEvent& signal)
196 _handle.promise().Bind(signal);
200 [[nodiscard]] promise_type& Promise() noexcept
202 return _handle.promise();
209 template <
typename T>
210 SyncWaitTask<T> SyncWaitPromise<T>::get_return_object() noexcept
212 return SyncWaitTask<T> { std::coroutine_handle<SyncWaitPromise<T>>::from_promise(*
this) };
215 inline SyncWaitTask<void> SyncWaitPromise<void>::get_return_object() noexcept
217 return SyncWaitTask<void> { std::coroutine_handle<SyncWaitPromise<void>>::from_promise(*
this) };
220 template <
typename T>
221 SyncWaitTask<T> MakeSyncWaitTask(Task<T> task)
223 if constexpr (std::is_void_v<T>)
224 co_await std::move(task);
226 co_return co_await std::move(task);
241T SyncWait(Task<T> task)
243 detail::SyncWaitEvent signal;
244 auto driver = detail::MakeSyncWaitTask<T>(std::move(task));
245 driver.Start(signal);
247 return driver.Promise().Take();
262template <
typename T,
typename Executor>
263T SyncWaitPumping(Task<T> task, Executor& executor)
265 detail::SyncWaitEvent signal;
269 signal.SetWaker([&executor] { executor.Post([] {}); });
270 auto driver = detail::MakeSyncWaitTask<T>(std::move(task));
271 driver.Start(signal);
272 executor.RunUntil([&signal] {
return signal.IsSet(); });
278 return driver.Promise().Take();