A single-threaded cooperatively scheduled runtime for async tasks.
Dispatcher implementations must pop and run tasks with one of the following:
PopAndRunAllReadyTasks() – Runs tasks until no progress can be made. The dispatcher will be woken when a task is ready to run.PopTaskToRun() and RunTask() – Run tasks individually. Dispatcher implementations MUST pop and run tasks until PopTaskToRun() returns nullptr. The dispatcher will not be woken when a task becomes ready unless PopTaskToRun() has returned nullptr.PopSingleTaskForThisWake() and RunTask() – Run tasks individually. It PopSingleTaskForThisWake is intended for use then only a single task (or one final task) should be executed. Is not necessary to call PopSingleTaskForThisWake() until it returns nullptr. Each call can result in one potentially redundant DoWake() call, so PopTaskToRun should be used one multiple tasks are executed.The base Dispatcher performs no allocations internally. Dispatcher offers Post overloads that allocate a task with the provided allocator, but their use is optional. C++20 coroutines can be posted to a Dispatcher with Post if C++20 is supported and the build target depends on //pw_async2:coro.
Public Member Functions | |
| Dispatcher (Dispatcher &)=delete | |
| Dispatcher & | operator= (Dispatcher &)=delete |
| Dispatcher (Dispatcher &&)=delete | |
| Dispatcher & | operator= (Dispatcher &&)=delete |
| virtual | ~Dispatcher () |
| void | Post (Task &task) |
| template<typename T > | |
| void | PostShared (const SharedPtr< T > &task) |
| template<typename TaskType , typename... Args, typename = std::enable_if_t<std::is_base_of_v<Task, TaskType>>> | |
| SharedPtr< TaskType > | Post (Allocator &allocator, Args &&... args) |
| template<typename Func = void, int &... kExplicitGuard, typename Arg , typename ActualFunc = std::conditional_t<std::is_void_v<Func>, std::decay_t<Arg>, Func>, typename = std::enable_if_t<!std::is_base_of_v<Task, ActualFunc>>> | |
| SharedPtr< FuncTask< ActualFunc > > | Post (Allocator &allocator, Arg &&func) |
| template<typename Func > | |
| SharedPtr< RunOnceTask< Func > > | RunOnce (Allocator &allocator, Func &&func) |
| template<typename Fut > | |
| SharedPtr< FutureTask< Fut > > | PostFuture (Allocator &allocator, Fut &&future) |
| void | LogRegisteredTasks () |
Protected Member Functions | |
| bool | PopAndRunAllReadyTasks () |
| Task * | PopTaskToRun () |
| Task * | PopTaskToRun (bool &has_posted_tasks) |
| Task * | PopSingleTaskForThisWake () |
| RunTaskResult | RunTask (Task &task) |
Private Member Functions | |
| virtual void | DoWake ()=0 |
Friends | |
| class | Task |
| class | Waker |
| template<typename > | |
| class | DispatcherForTestFacade |
|
inlinevirtual |
Removes references to this Dispatcher from all linked Tasks and Wakers.
|
privatepure virtual |
Sends a wakeup signal to this Dispatcher.
This method's implementation must ensure that the Dispatcher runs at some point in the future.
DoWake() will only be called once until one of the following occurs:
PopAndRunAllReadyTasks() is called,PopTaskToRun() returns nullptr, orPopSingleTaskForThisWake() is called.internal::lock() may or may not be held here, so it must not be acquired by DoWake, nor may DoWake assume that it has been acquired. Implemented in pw::async2::BasicDispatcher, pw::async2::DispatcherForTestFacade< Native >, pw::async2::EpollDispatcher, and pw::async2::NotifiedDispatcher.
| void pw::async2::Dispatcher::LogRegisteredTasks | ( | ) |
Outputs log statements about the tasks currently registered with this dispatcher.
|
protected |
Pops and runs tasks until there are no tasks ready to run.
This function may be called by dispatcher implementations to run tasks. This is a high-level function that runs all ready tasks without logging or metrics. For more control, use PopTaskToRun and RunTask.
| true | The dispatcher has posted tasks, but they are sleeping. |
| false | The dispatcher has no posted tasks. |
|
inlineprotected |
Pop a single task to run. Each call to PopSingleTaskForThisWake can result in up to one DoWake() call, so use PopTaskToRun or PopAndRunAllReadyTasks to run multiple tasks.
|
inlineprotected |
Pops a task and marks it as running. The task must be passed to RunTask.
PopTaskToRun MUST be called repeatedly until it returns nullptr, at which point the dispatcher will request a wake.
|
inlineprotected |
PopTaskToRun overload that optionally reports the whether the Dispatcher has registered tasks. This allows callers to distinguish between there being no woken tasks and no posted tasks at all.
Like the no-argument overload, PopTaskToRun MUST be called repeatedly until it returns nullptr.
| [out] | has_posted_tasks | Set to true if the dispatcher has at least one task posted, potentially including the task that was popped. Set to false if the dispatcher has no posted tasks. |
nullptr if there are no ready tasks.
|
inline |
Allocates a Task defined by the provided function and posts it as with PostShared. The function must take a pw::async2::Context as its only argument and return a Poll<T>.
This function supports both explicitly and implicitly specified function types. If Func is explicitly specified, it is used as-is. If Func is not specified, it is deduced as std::decay_t<Func>.
|
inline |
Tells the Dispatcher to run Task to completion. This method does not block.
After Post is called, Task::Pend will be invoked once. If Task::Pend does not complete, the Dispatcher will wait until the Task is "awoken", at which point it will call Pend again until the Task completes.
This method is thread-safe and interrupt-safe.
|
inline |
Allocates and posts a FutureTask that runs a future to completion.
PostFuture is intended for test and occasional production use. A FutureTask does not contain logic, and relying too much on FutureTasks could push logic out of async tasks, which nullifies the benefits of pw_async2. Creating a task for each future is also less efficient than having one task work with multiple futures.
|
inline |
Posts a dynamically allocated task to the dispatcher. Functions the same as Post, except the dispatcher takes shared reference to the task, which it frees when the task completes.
task must NOT be nullptr.
|
inline |
Runs a function object once on the Dispatcher. Allocates the wrapper task with allocator. The Dispatcher frees it when it completes.
Use RunOnceTask to declare a task that runs a function once without dynamic allocation.
RunOnce should be used rarely, such as in tests, truly one-off cases, or as a last resort for sync-async interop. pw_async2 should not be used as a work queue. Overuse of RunOnceTask forfeits the benefits of pw_async2, scattering logic across a mess of callbacks instead of organizing it linearly in a task.
|
inlineprotected |
Runs the task that was returned from PopTaskToRun.
Task object after RunTask returns! The task could have destroyed, either by the dispatcher or another thread, even if RunTask returns kActive. It is only safe to access a popped task before calling RunTask, since it is marked as running and will not be destroyed until after it runs.