47template <
typename Ret>
72 { a.await_suspend(std::move(task)) }
noexcept -> std::same_as<void>;
88 { a.await_suspend(std::move(factory)) }
noexcept -> std::same_as<void>;
89 { a.num_awaiters() } -> std::convertible_to<int>;
107 std::shared_ptr<EpochContext>
epoch{};
152 std::vector<NodeInfo const*> ReadDependencies;
153 std::vector<NodeInfo const*> WriteDependencies;
213 return awaiter_count_.fetch_sub(count, std::memory_order_acq_rel) == count;
229 if (!
exception_.exchange(
true, std::memory_order_acq_rel))
245 node.
epoch = std::move(epoch);
258 if (node.owner !=
this)
return;
259 if (from_destructor && node.explicit_sink && std::uncaught_exceptions() > 0)
263 "propagate_exceptions_to sink destroyed during exception unwinding before coroutine unhandled_exception()");
267 node.prev->next = node.next;
273 node.
owner =
nullptr;
277 node.explicit_sink =
false;
284 if (
exception_.load(std::memory_order_acquire))
294 if (
exception_.load(std::memory_order_acquire)) std::rethrow_exception(
eptr_);
319 template <
typename Task>
320 requires std::derived_from<std::remove_cvref_t<Task>,
BasicTask>
323 return std::forward<Task>(task);
330 static_assert(
sizeof(T) == 0,
331 "co_await expression does not match any known TaskAwaitable or TaskFactoryAwaitable type.");
377 template <
typename A>
static void note_await_dependency(
TaskHandle handle, A
const& awaitable)
382 if constexpr (
requires { awaitable.debug_each_dependency(record); })
384 awaitable.debug_each_dependency(record);
386 else if constexpr (
requires {
388 awaitable.debug_task_role();
403 handle.coroutine().resume();
410 handle.coroutine().destroy();
434 return std::noop_coroutine();
437 auto nested = task.release_ownership();
438 CHECK(nested,
"coroutine handle was not exclusively owned!");
440 if (nested == current)
447 nested.promise().continuation_ = current;
452 auto nested_task = nested.promise().take_ownership();
454 return std::noop_coroutine();
457 nested.promise().mark_started();
459 return nested.coroutine();
474 [[maybe_unused]]
int prior_count = this->
add_awaiter();
510 struct InitialAwaiter
514 [[nodiscard]]
constexpr bool await_ready()
noexcept {
return false; }
515 void await_suspend(std::coroutine_handle<>)
noexcept { TaskPromiseBase::note_suspended(promise->
self()); }
516 constexpr void await_resume()
noexcept {}
518 return InitialAwaiter{
this};
531 [[nodiscard]]
constexpr bool await_ready()
noexcept {
return false; }
533 std::coroutine_handle<> await_suspend(std::coroutine_handle<>)
noexcept
535 auto completed = promise->
self();
540 bool const direct_transfer =
545 TaskPromiseBase::destroy_and_track(completed);
559 if (continuation_exception)
560 *continuation_exception = eptr;
565 if (!direct_transfer)
567 auto continuation_task =
continuation.promise().take_ownership();
568 BasicTask::reschedule(std::move(continuation_task));
569 return std::noop_coroutine();
576 return std::noop_coroutine();
579 void await_resume()
noexcept {}
581 return FinalAwaiter{
this};
600 bool const originating_failure = !
exception_.load(std::memory_order_acquire);
601 auto eptr = std::current_exception();
618 CHECK(
scheduler->accepts_route(route),
"scheduler does not accept task route",
static_cast<int>(route.
domain),
640 auto handle = std::coroutine_handle<AsyncTaskPromise>::from_promise(*
this);
659 [[nodiscard]]
std::optional<
int>
device() const noexcept {
return device_; }
665 template <CudaTaskAwaitable Awaiter> Awaiter&&
await_transform(Awaiter&& awaiter)
noexcept
667 return std::forward<Awaiter>(awaiter);
676 CHECK(!this->
has_started(),
"cannot bind a CUDA task device after the task has started");
701 std::optional<int> device_{};
741 if (
auto const parent_device =
cuda_promise(parent).device()) child_promise.bind_device(*parent_device);
750 auto* scheduler = from.promise().scheduler();
751 CHECK(scheduler,
"running task has no scheduler route");
753 if (scheduler != to.promise().scheduler())
return false;
754 if (from.domain() != to.domain())
return false;
755 return scheduler->can_direct_transfer(from, to);
780 : handle_(std::exchange(other.handle_, {})), count_(std::exchange(other.count_, 0))
790 this->release_outstanding();
791 handle_ = std::exchange(other.handle_, {});
792 count_ = std::exchange(other.count_, 0);
807 this->release_outstanding();
830 void release_outstanding() noexcept
850 TaskPromiseBase::note_await_dependency(current, awaitable);
852 using await_return_type =
decltype(awaitable.await_suspend(std::declval<BasicTask>()));
853 if constexpr (std::is_void_v<await_return_type>)
860 else if constexpr (std::is_same_v<await_return_type, BasicTask>)
868 static_assert(std::is_same_v<await_return_type, void>,
869 "Unsupported await_suspend() return type: must be void or BasicTask");
876 TaskPromiseBase::note_await_dependency(current, awaitable);
879 awaitable.await_suspend(std::move(factory));
913 if constexpr (std::is_lvalue_reference_v<A>)
919 return std::move(
awaitable).await_resume();
948 static_cast<void>(promise);
949 static_cast<void>(
value);
976 if constexpr (std::is_lvalue_reference_v<A>)
982 return std::move(
awaitable).await_resume();
994 return TaskHandle(std::coroutine_handle<>::from_address(
handle.address()), std::addressof(
handle.promise()),
995 Promise::task_domain);
Exception hierarchy for async/dataflow operations.
Debug metadata nodes used for async DAG visualization.
Promise-neutral coroutine task ownership and the public AsyncTask type.
Inline implementation of promise-neutral task ownership and nesting.
static void register_task(std::coroutine_handle<> h)
Registers a newly-created coroutine handle.
static void leak_task(std::coroutine_handle<> h)
Marks a coroutine handle as leaked.
static void record_task_dependencies(std::coroutine_handle<> h, std::vector< async::NodeInfo const * > const &read_dependencies, std::vector< async::NodeInfo const * > const &write_dependencies)
Records constructor-discovered coarse DAG dependencies for a coroutine.
static void destroy_task(std::coroutine_handle<> h)
Marks a coroutine handle as destroyed.
static void mark_suspended(std::coroutine_handle<> h)
Marks a coroutine handle as suspended.
static void mark_running(std::coroutine_handle<> h)
Marks a coroutine handle as currently running.
static void record_unhandled_exception(std::coroutine_handle<> h, std::exception_ptr exception, bool originating_failure) noexcept
Records an exception escaping a coroutine and optionally captures its live DAG.
EpochTaskRole
Role of a coroutine relative to an epoch context.
Definition task_registry_debug.hpp:56
static void record_await_dependency(std::coroutine_handle<> h, async::NodeInfo const *node, EpochTaskRole role)
Records a buffer dependency discovered at a concrete co_await site.
Promise type for ordinary AsyncTask coroutines.
Definition async_task_promise.hpp:632
AsyncTask get_return_object() noexcept
Definition async_task_promise.hpp:638
static constexpr TaskDomain task_domain
Definition async_task_promise.hpp:634
Canonical host-oriented coroutine task type.
Definition async_task.hpp:196
Move-only promise-neutral ownership claim for a Uni20 coroutine.
Definition async_task.hpp:103
static void reschedule(BasicTask task)
Reschedule a task when it becomes the sole ownership claimant.
Definition async_task_impl.hpp:11
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
Promise type for CUDA-constrained CudaTask coroutines.
Definition async_task_promise.hpp:646
static constexpr TaskDomain task_domain
Definition async_task_promise.hpp:648
std::optional< int > device() const noexcept
Return the task's established CUDA device affinity, if any.
Definition async_task_promise.hpp:659
void select_device(int device)
Select the device used for subsequent CUDA task activations.
Definition async_task_promise.hpp:693
CudaTask get_return_object() noexcept
Definition cuda_task.hpp:40
void bind_device(int device)
Bind the CUDA device before the coroutine starts.
Definition async_task_promise.hpp:673
Awaiter && await_transform(Awaiter &&awaiter) noexcept
Pass through an explicitly opted-in CUDA task awaiter.
Definition async_task_promise.hpp:665
CUDA-constrained public task type used for typed initial admission.
Definition cuda_task.hpp:14
Internal route for resuming an already-bound coroutine task.
Definition scheduler.hpp:64
Records node information for DAG/debugging visualization.
Definition async_node.hpp:171
Factory for producing multiple BasicTask ownership claims for one coroutine.
Definition async_task_promise.hpp:766
TaskFactory(TaskFactory &&other) noexcept
Definition async_task_promise.hpp:779
TaskFactory(TaskFactory const &)=delete
TaskFactory & operator=(TaskFactory &&other) noexcept
Move assignment.
Definition async_task_promise.hpp:786
BasicTask take_next()
Dispense the next BasicTask from the pool of shared ownership handles.
Definition async_task_promise.hpp:772
~TaskFactory() noexcept
Destructor returns any unused ownership claims and may destroy the coroutine.
Definition async_task_promise.hpp:804
TaskFactory & operator=(TaskFactory const &)=delete
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
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
Shared non-polymorphic implementation for Uni20 task promises.
Definition async_task_promise.hpp:99
IScheduler * scheduler() const noexcept
Return the scheduler currently recorded for this task.
Definition async_task_promise.hpp:357
static auto suspend_task_awaitable(TaskHandle current, A &awaitable)
Execute await_suspend for TaskAwaitable and apply TaskRegistry tracking.
Definition async_task_promise.hpp:847
static constexpr int kNoPreferredNumaNode
Definition async_task_promise.hpp:140
bool release_awaiter(int count) noexcept
Decrease the number of active awaiters by a specified count.
Definition async_task_promise.hpp:211
std::atomic< bool > cancel_on_resume_
If true, then when the coroutine is next resumed (i.e.
Definition async_task_promise.hpp:138
static void prepare_nested_route(TaskHandle parent, TaskHandle child)
Complete an unbound child's route before nested execution.
Definition async_task_promise.hpp:723
constexpr void return_void() noexcept
Called when the coroutine returns normally.
Definition async_task_promise.hpp:585
uint64_t Instance
Definition async_task_promise.hpp:147
TaskHandle initialize_task(std::coroutine_handle< Promise > handle) noexcept
Cache erased self-identity and register the initial ownership claim.
Definition async_task_promise.hpp:495
auto await_transform(T &&)
Fallback await_transform overload that rejects unsupported awaitables.
Definition async_task_promise.hpp:328
friend class BasicTask
Definition async_task_promise.hpp:628
bool is_cancel_on_resume() const noexcept
Reports whether cancellation-on-resume is currently set.
Definition async_task_promise.hpp:302
auto await_transform(A &a)
Transform an awaiter to transfer one task ownership claim.
Definition async_impl.hpp:74
static std::coroutine_handle resolve_await_suspend_result(TaskHandle current, BasicTask &&task)
Resolve an await_suspend task return value into a coroutine transfer handle.
Definition async_task_promise.hpp:429
std::string Name
Definition async_task_promise.hpp:146
auto initial_suspend() noexcept
Suspend immediately on coroutine entry.
Definition async_task_promise.hpp:508
void register_exception_sink(ExceptionSinkNode &node, std::shared_ptr< EpochContext > epoch, bool explicit_sink)
Register one exception propagation sink with this promise.
Definition async_task_promise.hpp:239
std::atomic< int > awaiter_count_
Number of active ownership claims on this coroutine.
Definition async_task_promise.hpp:127
void set_exception(std::exception_ptr e) noexcept
Record an exception for deferred rethrow on resume.
Definition async_task_promise.hpp:227
BasicTask take_ownership() noexcept
Acquire exclusive ownership of the coroutine.
Definition async_task_promise.hpp:472
constexpr TaskPromiseBase() noexcept=default
Default-construct the promise.
int add_awaiter() noexcept
Increase the number of active awaiters by one.
Definition async_task_promise.hpp:218
auto await_transform(A &&a)
TaskFactory take_shared_ownership(int count)
Acquire shared ownership of the coroutine for use with multi-await constructs.
Definition async_task_promise.hpp:845
int add_awaiter(int count) noexcept
Increase the number of active awaiters by a specified count.
Definition async_task_promise.hpp:223
static void note_running(TaskHandle handle) noexcept
Record that a coroutine has transitioned into a runnable/running state.
Definition async_task_promise.hpp:367
bool has_started() const noexcept
Query whether the coroutine has begun executing.
Definition async_task_promise.hpp:354
ExceptionSinkNode * exception_sinks_head_
Definition async_task_promise.hpp:148
bool release_awaiter() noexcept
Decrease the number of active awaiters by one.
Definition async_task_promise.hpp:206
TaskPromiseBase(Args &&... args)
Construct the promise and process coroutine arguments for debug metadata.
Definition async_task_promise.hpp:181
void unregister_exception_sink(ExceptionSinkNode &node, bool from_destructor) noexcept
Unregister one exception propagation sink from this promise.
Definition async_task_promise.hpp:256
void set_preferred_numa_node(std::optional< int > node) noexcept
Set the preferred NUMA node recorded for this coroutine.
Definition async_task_promise.hpp:336
static bool can_transfer_directly(TaskHandle from, TaskHandle to) noexcept
Report whether symmetric transfer is valid for two prepared task routes.
Definition async_task_promise.hpp:746
void unhandled_exception()
Called on unhandled exception escaping the coroutine.
Definition async_task_promise.hpp:588
std::atomic< bool > exception_
EpochContext can inject an exception into a coroutine, which will be thrown when resuming from an awa...
Definition async_task_promise.hpp:133
void set_cancel_on_resume() noexcept
Mark the coroutine for cancellation at next resume.
Definition async_task_promise.hpp:298
void mark_started() noexcept
Mark the coroutine as having been scheduled to start executing.
Definition async_task_promise.hpp:351
std::exception_ptr get_exception() noexcept
Get the current exception pointer, or nullptr if there is no current exception.
Definition async_task_promise.hpp:282
TaskHandle destroy_with_continuation() noexcept
safely destroy this coroutine, returning the continuation_ (which also must now be destroyed)
Definition async_task_promise.hpp:188
std::exception_ptr * continuation_exception_
Destination for an exception returned by a directly awaited task.
Definition async_task_promise.hpp:122
auto final_suspend() noexcept
Definition async_task_promise.hpp:525
static void destroy_and_track(TaskHandle handle) noexcept
Destroy a coroutine handle while recording destruction in the registry.
Definition async_task_promise.hpp:407
static void validate_scheduler_route(IScheduler *scheduler, TaskRoute route)
Validate a prospective task route without changing promise state.
Definition async_task_promise.hpp:615
static void note_leaked(TaskHandle handle) noexcept
Record that a coroutine has been intentionally leaked.
Definition async_task_promise.hpp:397
static void note_suspended(TaskHandle handle) noexcept
Record that a coroutine has suspended and is waiting for resumption.
Definition async_task_promise.hpp:370
static void suspend_factory_awaitable(TaskHandle current, A &awaitable)
Execute await_suspend for TaskFactoryAwaitable and apply TaskRegistry tracking.
Definition async_task_promise.hpp:873
TaskHandle release_ownership()
Release ownership of the coroutine and return it, if it was exclusively owned.
Definition async_task_promise.hpp:488
TaskHandle self() noexcept
Return this promise's erased coroutine identity.
Definition async_task_promise.hpp:360
std::atomic< bool > started_
Tracks whether the coroutine has been scheduled or otherwise started.
Definition async_task_promise.hpp:112
std::optional< int > preferred_numa_node() const noexcept
Retrieve the preferred NUMA node for this coroutine.
Definition async_task_promise.hpp:343
void rethrow_exception()
Throw the current exception, if there is one.
Definition async_task_promise.hpp:292
static void resume_and_track(TaskHandle handle)
Resume a coroutine handle while recording the running transition.
Definition async_task_promise.hpp:400
std::exception_ptr eptr_
Definition async_task_promise.hpp:134
Task && await_transform(Task &&task) noexcept
Pass through a concrete task that uses the shared basic task representation.
Definition async_task_promise.hpp:321
TaskHandle continuation_
Uni20 task coroutines are nestable.
Definition async_task_promise.hpp:117
std::atomic< int > preferred_numa_node_
Preferred NUMA node recorded for the coroutine.
Definition async_task_promise.hpp:143
~TaskPromiseBase() noexcept
Definition async_task_promise.hpp:198
Raised when an AsyncTask is cancelled before completion.
Definition async_errors.hpp:44
Concept for the valid return types of await_suspend.
Definition async_task_promise.hpp:48
Identifies an explicitly opted-in CUDA task awaiter.
Definition async_task_promise.hpp:33
Concept for awaitables that accept promise-neutral task ownership.
Definition async_task_promise.hpp:61
Concept for awaitables that support shared promise-neutral ownership.
Definition async_task_promise.hpp:87
Awaitable that can hold one ownership claim in a multi-input join.
Definition async_task_promise.hpp:71
Promise concept accepted by Uni20 task machinery.
Definition async_task.hpp:50
cuda::ResourceLease< HandleSlot > handle
Definition cublas/execution.cpp:33
locale_t value
Definition data_table.cpp:49
bool continuation
Definition display.cpp:148
This represents the reverse-mode adjoint for functions of complex variables, assuming a real-valued s...
Definition async/async.hpp:26
TaskRoute task_route(TaskHandle handle) noexcept
Return the current scheduling requirements recorded by a task.
Definition async_task_promise.hpp:715
CudaTaskPromise & cuda_promise(TaskHandle handle) noexcept
Narrow an erased task promise after verifying that it is CUDA-specific.
Definition async_task_promise.hpp:707
void propagate_unhandled_writer_exception(EpochContext *epoch, std::exception_ptr eptr) noexcept
Inject an unhandled writer-side coroutine exception into an epoch.
Definition epoch_context.hpp:836
void ProcessCoroutineArgument(TaskPromiseBase *promise, T const &value)
Process a coroutine argument for debug metadata (default no-op).
Definition async_task_promise.hpp:946
TaskDomain
Execution domain declared by a concrete Uni20 task promise.
Definition async_task.hpp:32
Defines internal task routing and the host-oriented scheduler interface.
Definition async_task.hpp:177
Marker base for awaiters that require a CudaTaskPromise handle.
Definition async_task_promise.hpp:29
Forwarding awaiter that transfers one task ownership claim to an awaitable.
Definition async_task_promise.hpp:885
bool await_ready()
Checks whether the wrapped awaitable is ready.
Definition async_task_promise.hpp:891
TaskPromiseBase & promise
Definition async_task_promise.hpp:887
A awaitable
Definition async_task_promise.hpp:886
auto await_suspend(std::coroutine_handle< Promise > handle)
Suspend using promise-neutral ownership-transfer semantics.
Definition async_task_promise.hpp:897
decltype(auto) await_resume()
Resume wrapped awaitable and register explicit exception sinks if provided.
Definition async_task_promise.hpp:904
Forwarding awaiter that transfers shared task ownership through a TaskFactory.
Definition async_task_promise.hpp:953
void await_suspend(std::coroutine_handle< Promise > handle)
Suspend using shared-ownership await-suspend semantics.
Definition async_task_promise.hpp:964
decltype(auto) await_resume()
Resume wrapped awaitable and return its await result.
Definition async_task_promise.hpp:971
bool await_ready()
Checks whether the wrapped awaitable is ready.
Definition async_task_promise.hpp:959
TaskPromiseBase & promise
Definition async_task_promise.hpp:955
A awaitable
Definition async_task_promise.hpp:954
Intrusive node describing one exception propagation sink.
Definition async_task_promise.hpp:103
TaskPromiseBase * owner
Definition async_task_promise.hpp:104
bool explicit_sink
Definition async_task_promise.hpp:108
ExceptionSinkNode * prev
Definition async_task_promise.hpp:105
ExceptionSinkNode * next
Definition async_task_promise.hpp:106
std::shared_ptr< EpochContext > epoch
Definition async_task_promise.hpp:107
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
#define CHECK(cond,...)
Definition trace.hpp:299
#define DEBUG_CHECK(cond,...)
Definition trace.hpp:608
#define TRACE_MODULE(m,...)
Definition trace.hpp:149
#define DEBUG_PRECONDITION(cond,...)
Definition trace.hpp:648
#define DEBUG_TRACE_MODULE(m,...)
Definition trace.hpp:511
#define CHECK_EQUAL(a, b,...)
Definition trace.hpp:309
#define DEBUG_CHECK_EQUAL(a, b,...)
Definition trace.hpp:618