14#if defined(__cpp_impl_coroutine) && __cpp_impl_coroutine >= 201902L
23namespace threadschedule
26template <
typename T =
void>
45 [[nodiscard]]
auto await_ready() const noexcept ->
bool
50 template <
typename Promise>
51 auto await_suspend(std::coroutine_handle<Promise> h)
const noexcept -> std::coroutine_handle<>
53 if (
auto cont = h.promise().continuation_; cont)
55 return std::noop_coroutine();
58 void await_resume() const noexcept
83class task_promise_base
86 task_promise_base() =
default;
88 auto initial_suspend() noexcept -> std::suspend_always
93 auto final_suspend() noexcept -> final_awaiter
98 void unhandled_exception() noexcept
100 exception_ = std::current_exception();
103 void rethrow_if_exception()
106 std::rethrow_exception(exception_);
109 std::coroutine_handle<> continuation_{};
112 std::exception_ptr exception_{};
154 struct promise_type : detail::task_promise_base<T>
156 auto get_return_object() noexcept -> task
158 return task{std::coroutine_handle<promise_type>::from_promise(*
this)};
161 void return_value(T value)
noexcept(std::is_nothrow_move_constructible_v<T>)
163 result_.emplace(std::move(value));
168 this->rethrow_if_exception();
169 return std::move(*result_);
173 std::optional<T> result_{};
176 task() noexcept = default;
178 task(task&& other) noexcept : handle_(std::exchange(other.handle_,
nullptr))
182 auto operator=(task&& other)
noexcept -> task&
187 handle_ = std::exchange(other.handle_,
nullptr);
197 task(task
const&) =
delete;
198 auto operator=(task
const&) -> task& =
delete;
200 [[nodiscard]]
auto handle() const noexcept -> std::coroutine_handle<promise_type>
207 std::coroutine_handle<promise_type> handle_;
209 [[nodiscard]]
auto await_ready() const noexcept ->
bool
214 auto await_suspend(std::coroutine_handle<> continuation)
noexcept -> std::coroutine_handle<>
216 handle_.promise().continuation_ = continuation;
220 auto await_resume() -> T
222 return handle_.promise().result();
226 auto operator co_await()
const&
noexcept -> awaiter
228 return awaiter{handle_};
231 auto operator co_await()
const&&
noexcept -> awaiter
233 return awaiter{handle_};
237 explicit task(std::coroutine_handle<promise_type> h) noexcept : handle_(h)
250 std::coroutine_handle<promise_type> handle_{};
286 struct promise_type : detail::task_promise_base<void>
288 auto get_return_object() noexcept -> task<
void>
290 return task<void>{std::coroutine_handle<promise_type>::from_promise(*
this)};
293 void return_void() noexcept
299 this->rethrow_if_exception();
303 task() noexcept = default;
305 task(task&& other) noexcept : handle_(std::exchange(other.handle_,
nullptr))
309 auto operator=(task&& other)
noexcept -> task<void>&
314 handle_ = std::exchange(other.handle_,
nullptr);
324 task(task
const&) =
delete;
325 auto operator=(task
const&) -> task<void>& =
delete;
327 [[nodiscard]]
auto handle() const noexcept -> std::coroutine_handle<promise_type>
334 std::coroutine_handle<promise_type> handle_;
336 [[nodiscard]]
auto await_ready() const noexcept ->
bool
341 auto await_suspend(std::coroutine_handle<> continuation)
noexcept -> std::coroutine_handle<>
343 handle_.promise().continuation_ = continuation;
349 handle_.promise().result();
353 auto operator co_await()
const&
noexcept -> awaiter
355 return awaiter{handle_};
358 auto operator co_await()
const&&
noexcept -> awaiter
360 return awaiter{handle_};
364 explicit task(std::coroutine_handle<promise_type> h) noexcept : handle_(h)
377 std::coroutine_handle<promise_type> handle_{};
410 auto initial_suspend() noexcept -> std::suspend_always
415 auto final_suspend() noexcept
419 [[nodiscard]]
auto await_ready() const noexcept ->
bool
424 void await_suspend(std::coroutine_handle<promise_type> h)
const noexcept
426 h.promise().finished_.store(
true, std::memory_order_release);
427 h.promise().finished_.notify_one();
430 void await_resume() const noexcept
437 auto get_return_object() -> sync_wait_task
439 return sync_wait_task{std::coroutine_handle<promise_type>::from_promise(*
this)};
442 void return_void() noexcept
446 void unhandled_exception() noexcept
448 exception_ = std::current_exception();
451 std::atomic<bool> finished_{
false};
452 std::exception_ptr exception_{};
455 explicit sync_wait_task(std::coroutine_handle<promise_type> h) : handle_(h)
459 sync_wait_task(sync_wait_task&& other) noexcept : handle_(std::exchange(other.handle_,
nullptr))
469 sync_wait_task(sync_wait_task
const&) =
delete;
470 auto operator=(sync_wait_task
const&) -> sync_wait_task& =
delete;
471 auto operator=(sync_wait_task&&) -> sync_wait_task& =
delete;
480 handle_.promise().finished_.wait(
false, std::memory_order_acquire);
485 if (handle_.promise().exception_)
486 std::rethrow_exception(handle_.promise().exception_);
490 std::coroutine_handle<promise_type> handle_;
518auto sync_wait(task<T> t) -> T
520 std::optional<T> result;
521 std::exception_ptr ex;
523 auto wrapper = [&result, &ex](task<T> inner) -> detail::sync_wait_task {
526 result.emplace(
co_await inner);
530 ex = std::current_exception();
534 auto sw = wrapper(std::move(t));
540 std::rethrow_exception(ex);
542 return std::move(*result);
558inline void sync_wait(task<void> t)
560 std::exception_ptr ex;
562 auto wrapper = [&ex](task<void> inner) -> detail::sync_wait_task {
569 ex = std::current_exception();
573 auto sw = wrapper(std::move(t));
579 std::rethrow_exception(ex);