Uni20
Asynchronous tensor and runtime library.
Loading...
Searching...
No Matches
async_task.hpp
Go to the documentation of this file.
1
6#pragma once
7
8#include "task_registry.hpp"
9
10#include <atomic>
11#include <concepts>
12#include <coroutine>
13#include <exception>
14#include <optional>
15#include <string>
17#include <utility>
18
19namespace uni20::async
20{
21
22class IScheduler;
23class TaskPromiseBase;
24class AsyncTaskPromise;
25class CudaTaskPromise;
26class TaskFactory;
27class AsyncTask;
28class CudaTask;
29
31enum class TaskDomain
32{
33 none,
34 host,
35 cuda,
36};
37
43{
45 std::optional<int> cuda_device{};
46};
47
49template <typename T>
50concept TaskPromise = std::derived_from<T, TaskPromiseBase> && requires {
51 { T::task_domain } -> std::convertible_to<TaskDomain>;
52};
53
60 public:
61 constexpr TaskHandle() noexcept = default;
62
63 template <TaskPromise Promise> [[nodiscard]] static TaskHandle from(std::coroutine_handle<Promise> handle) noexcept;
64
65 [[nodiscard]] explicit constexpr operator bool() const noexcept { return static_cast<bool>(coroutine_); }
66
67 [[nodiscard]] constexpr std::coroutine_handle<> coroutine() const noexcept { return coroutine_; }
68
69 [[nodiscard]] TaskPromiseBase& promise() const noexcept;
70
72 [[nodiscard]] TaskDomain domain() const noexcept
73 {
75 return domain_;
76 }
77
78 [[nodiscard]] bool done() const noexcept { return !coroutine_ || coroutine_.done(); }
79
80 friend constexpr bool operator==(TaskHandle lhs, TaskHandle rhs) noexcept
81 {
82 return lhs.coroutine_ == rhs.coroutine_;
83 }
84
85 private:
86 TaskHandle(std::coroutine_handle<> coroutine, TaskPromiseBase* promise, TaskDomain domain) noexcept
87 : coroutine_(coroutine), promise_(promise), domain_(domain)
88 {
89 DEBUG_CHECK_EQUAL(static_cast<bool>(coroutine_), promise_ != nullptr);
90 DEBUG_CHECK_EQUAL(static_cast<bool>(coroutine_), domain_ != TaskDomain::none);
91 }
92
93 std::coroutine_handle<> coroutine_{};
94 TaskPromiseBase* promise_ = nullptr;
96
97 friend class TaskPromiseBase;
98};
99
104 public:
106 BasicTask() noexcept = default;
107
108 BasicTask(BasicTask const&) = delete;
109 BasicTask& operator=(BasicTask const&) = delete;
110
112 BasicTask(BasicTask&& other) noexcept
113 : handle_(std::exchange(other.handle_, {})), await_exception_(std::exchange(other.await_exception_, {}))
114 {}
115
117 BasicTask& operator=(BasicTask&& other) noexcept;
118
120 ~BasicTask() noexcept;
121
122 [[nodiscard]] explicit operator bool() const noexcept { return static_cast<bool>(handle_); }
123
125 [[nodiscard]] TaskHandle handle() const noexcept { return handle_; }
126
128 [[nodiscard]] std::coroutine_handle<> coroutine_handle() const noexcept { return handle_.coroutine(); }
129
131 BasicTask& debug_name(std::string const& label)
132 {
134 return *this;
135 }
136
138 void resume();
139
141 void abandon_leak();
142
144 [[nodiscard]] TaskHandle release_handle();
145
147 void set_cancel_on_resume() noexcept;
148
150 void exception_on_resume(std::exception_ptr error) noexcept;
151
153 void destroy() noexcept;
154
156 [[nodiscard]] bool set_scheduler(IScheduler* scheduler);
157
158 [[nodiscard]] std::optional<int> preferred_numa_node() const noexcept;
159 void set_preferred_numa_node(std::optional<int> node) noexcept;
160
162 static void reschedule(BasicTask task);
163
165 [[nodiscard]] static BasicTask make_sole_owner(BasicTask&& task);
166
167 [[nodiscard]] bool await_ready() const noexcept { return !handle_ || handle_.done(); }
168
170 template <TaskPromise ParentPromise>
171 std::coroutine_handle<> await_suspend(std::coroutine_handle<ParentPromise> parent);
172
173 void await_resume();
174
175 protected:
177 {};
178
179 explicit BasicTask(TaskHandle handle, construction_key) noexcept : handle_(handle) {}
180
181 private:
182 [[nodiscard]] bool can_destroy_coroutine(TaskHandle handle) const noexcept;
183 [[nodiscard]] TaskHandle release_ownership();
184 void release() noexcept;
185 void destroy_owned_coroutine() noexcept;
186
187 TaskHandle handle_{};
188 std::exception_ptr await_exception_{};
189
190 friend class TaskPromiseBase;
191 friend class TaskFactory;
192 friend struct AsyncTaskTestAccess;
193};
194
196class AsyncTask final : public BasicTask {
197 public:
200
201 AsyncTask() = default;
202 AsyncTask(AsyncTask const&) = delete;
203 AsyncTask& operator=(AsyncTask const&) = delete;
204 AsyncTask(AsyncTask&&) noexcept = default;
205 AsyncTask& operator=(AsyncTask&&) noexcept = default;
206
207 AsyncTask& debug_name(std::string const& label)
208 {
209 this->BasicTask::debug_name(label);
210 return *this;
211 }
212
213 private:
214 explicit AsyncTask(TaskHandle handle) noexcept : BasicTask(handle, construction_key{}) {}
215
216 friend class AsyncTaskPromise;
217};
218
219} // namespace uni20::async
220
221#include "async_task_promise.hpp"
Defines shared and concrete task coroutine promises.
static void name_task(std::coroutine_handle<> h, std::string const &label)
Assigns an optional human-readable label to a coroutine task.
Promise type for ordinary AsyncTask coroutines.
Definition async_task_promise.hpp:632
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
AsyncTask & operator=(AsyncTask const &)=delete
friend class AsyncTaskPromise
Definition async_task.hpp:216
AsyncTask & debug_name(std::string const &label)
Definition async_task.hpp:207
AsyncTask(AsyncTask const &)=delete
AsyncTask(AsyncTask &&) noexcept=default
Move-only promise-neutral ownership claim for a Uni20 coroutine.
Definition async_task.hpp:103
bool set_scheduler(IScheduler *scheduler)
Install the scheduler used for later resumption.
Definition async_task_impl.hpp:142
static void reschedule(BasicTask task)
Reschedule a task when it becomes the sole ownership claimant.
Definition async_task_impl.hpp:11
BasicTask(TaskHandle handle, construction_key) noexcept
Definition async_task.hpp:179
BasicTask & debug_name(std::string const &label)
Assign an optional debug label.
Definition async_task.hpp:131
~BasicTask() noexcept
Release the ownership claim and destroy the frame when appropriate.
Definition async_task_impl.hpp:133
void await_resume()
Definition async_task_impl.hpp:186
std::coroutine_handle coroutine_handle() const noexcept
Return the generic coroutine handle for diagnostics.
Definition async_task.hpp:128
void abandon_leak()
Intentionally leak the coroutine during emergency unwinding.
Definition async_task_impl.hpp:84
void exception_on_resume(std::exception_ptr error) noexcept
Store an exception for delivery on the next resume.
Definition async_task_impl.hpp:97
void resume()
Resume the coroutine and transfer this ownership claim.
Definition async_task_impl.hpp:77
BasicTask() noexcept=default
Construct an empty task.
TaskHandle release_handle()
Release this ownership claim to a scheduler activation.
Definition async_task_impl.hpp:51
friend struct AsyncTaskTestAccess
Definition async_task.hpp:192
void set_preferred_numa_node(std::optional< int > node) noexcept
Definition async_task_impl.hpp:156
BasicTask & operator=(BasicTask const &)=delete
static BasicTask make_sole_owner(BasicTask &&task)
Retain a task only when it is the sole ownership claimant.
Definition async_task_impl.hpp:23
bool await_ready() const noexcept
Definition async_task.hpp:167
void destroy() noexcept
Destroy an exclusively owned coroutine.
Definition async_task_impl.hpp:135
TaskHandle handle() const noexcept
Return the erased task identity.
Definition async_task.hpp:125
void set_cancel_on_resume() noexcept
Request cancellation before the next resume.
Definition async_task_impl.hpp:91
std::optional< int > preferred_numa_node() const noexcept
Definition async_task_impl.hpp:150
std::coroutine_handle await_suspend(std::coroutine_handle< ParentPromise > parent)
Await a nested task from any Uni20 task promise type.
Definition async_task_impl.hpp:162
Internal route for resuming an already-bound coroutine task.
Definition scheduler.hpp:64
Factory for producing multiple BasicTask ownership claims for one coroutine.
Definition async_task_promise.hpp:766
Non-owning erased identity for one Uni20 coroutine frame.
Definition async_task.hpp:59
TaskDomain domain() const noexcept
Return the execution domain declared by the concrete promise.
Definition async_task.hpp:72
friend constexpr bool operator==(TaskHandle lhs, TaskHandle rhs) noexcept
Definition async_task.hpp:80
bool done() const noexcept
Definition async_task.hpp:78
friend class TaskPromiseBase
Definition async_task.hpp:97
constexpr std::coroutine_handle coroutine() const noexcept
Definition async_task.hpp:67
TaskPromiseBase & promise() const noexcept
Definition async_task_promise.hpp:998
static TaskHandle from(std::coroutine_handle< Promise > handle) noexcept
Definition async_task_promise.hpp:991
constexpr TaskHandle() noexcept=default
Shared non-polymorphic implementation for Uni20 task promises.
Definition async_task_promise.hpp:99
Promise concept accepted by Uni20 task machinery.
Definition async_task.hpp:50
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
Definition qnum.hpp:403
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
TaskDomain
Execution domain declared by a concrete Uni20 task promise.
Definition async_task.hpp:32
Definition async_task.hpp:177
Execution requirements used to validate a scheduler route.
Definition async_task.hpp:43
std::optional< int > cuda_device
Definition async_task.hpp:45
TaskDomain domain
Definition async_task.hpp:44
Selects the task-registry implementation for the current build mode.
#define DEBUG_PRECONDITION(cond,...)
Definition trace.hpp:648
#define DEBUG_CHECK_EQUAL(a, b,...)
Definition trace.hpp:618