From ab196b9adfba511e1880fa78c8fea3b3edbde083 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Tue, 12 Nov 2024 12:21:09 -0300 Subject: [PATCH] allow sending progress from Task coroutines by using co_yield --- loader/include/Geode/utils/Task.hpp | 39 ++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/loader/include/Geode/utils/Task.hpp b/loader/include/Geode/utils/Task.hpp index 6971a2fc..7a40e3e4 100644 --- a/loader/include/Geode/utils/Task.hpp +++ b/loader/include/Geode/utils/Task.hpp @@ -9,7 +9,7 @@ namespace geode { namespace geode_internal { - template + template struct TaskPromise; template @@ -161,7 +161,7 @@ namespace geode { template friend class Task; - template + template friend struct geode_internal::TaskPromise; template @@ -322,7 +322,7 @@ namespace geode { template friend class Task; - template + template friend struct geode_internal::TaskPromise; template @@ -924,12 +924,22 @@ namespace geode { // // The body of the coroutine is ran in whatever thread it got called in. // TODO: maybe guarantee main thread? +// +// The coroutine can also yield progress values using `co_yield`: +// ``` +// Task someTask() { +// for (int i = 0; i < 10; i++) { +// co_yield i; +// } +// co_return "done!"; +// } +// ``` namespace geode { namespace geode_internal { - template + template struct TaskPromise { - using MyTask = Task; + using MyTask = Task; std::weak_ptr m_handle; ~TaskPromise() { @@ -948,10 +958,15 @@ namespace geode { return handle; } - void return_value(T&& x) { + void return_value(T x) { MyTask::finish(m_handle.lock(), std::move(x)); } + std::suspend_never yield_value(P value) { + MyTask::progress(m_handle.lock(), std::move(value)); + return {}; + } + bool isCancelled() { if (auto p = m_handle.lock()) { return p->is(MyTask::Status::Cancelled); @@ -968,8 +983,8 @@ namespace geode { return task.isFinished(); } - template - void await_suspend(std::coroutine_handle> handle) { + template + void await_suspend(std::coroutine_handle> handle) { if (handle.promise().isCancelled()) { handle.destroy(); return; @@ -981,7 +996,7 @@ namespace geode { handle.destroy(); return; } - parentHandle->m_extraData = std::make_unique::Handle::ExtraData>( + parentHandle->m_extraData = std::make_unique::Handle::ExtraData>( static_cast(new EventListener>( [handle](auto* event) { if (event->getValue()) { @@ -1014,7 +1029,7 @@ auto operator co_await(geode::Task task) { return geode::geode_internal::TaskAwaiter{task}; } -template -struct std::coroutine_traits, Args...> { - using promise_type = geode::geode_internal::TaskPromise; +template +struct std::coroutine_traits, Args...> { + using promise_type = geode::geode_internal::TaskPromise; }; \ No newline at end of file