C/C++ API Reference
Loading...
Searching...
No Matches
pw::async2::Dispatcher Class Referenceabstract

Overview

A single-threaded cooperatively scheduled runtime for async tasks.

Dispatcher implementations must pop and run tasks with one of the following:

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.

Inheritance diagram for pw::async2::Dispatcher:
pw::async2::RunnableDispatcher pw::async2::BasicDispatcher pw::async2::DispatcherForTestFacade< Native > pw::async2::EpollDispatcher pw::async2::NotifiedDispatcher

Public Member Functions

 Dispatcher (Dispatcher &)=delete
 
Dispatcheroperator= (Dispatcher &)=delete
 
 Dispatcher (Dispatcher &&)=delete
 
Dispatcheroperator= (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 ()
 
TaskPopTaskToRun ()
 
TaskPopTaskToRun (bool &has_posted_tasks)
 
TaskPopSingleTaskForThisWake ()
 
RunTaskResult RunTask (Task &task)
 

Private Member Functions

virtual void DoWake ()=0
 

Friends

class Task
 
class Waker
 
template<typename >
class DispatcherForTestFacade
 

Constructor & Destructor Documentation

◆ ~Dispatcher()

virtual pw::async2::Dispatcher::~Dispatcher ( )
inlinevirtual

Removes references to this Dispatcher from all linked Tasks and Wakers.

Member Function Documentation

◆ DoWake()

virtual void pw::async2::Dispatcher::DoWake ( )
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:

Note
The 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.

◆ LogRegisteredTasks()

void pw::async2::Dispatcher::LogRegisteredTasks ( )

Outputs log statements about the tasks currently registered with this dispatcher.

◆ PopAndRunAllReadyTasks()

bool pw::async2::Dispatcher::PopAndRunAllReadyTasks ( )
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.

Return values
trueThe dispatcher has posted tasks, but they are sleeping.
falseThe dispatcher has no posted tasks.

◆ PopSingleTaskForThisWake()

Task * pw::async2::Dispatcher::PopSingleTaskForThisWake ( )
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.

◆ PopTaskToRun() [1/2]

Task * pw::async2::Dispatcher::PopTaskToRun ( )
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.

◆ PopTaskToRun() [2/2]

Task * pw::async2::Dispatcher::PopTaskToRun ( bool &  has_posted_tasks)
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.

Parameters
[out]has_posted_tasksSet 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.
Returns
A pointer to a task that is ready to run, or nullptr if there are no ready tasks.

◆ Post() [1/3]

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 > > pw::async2::Dispatcher::Post ( Allocator allocator,
Arg &&  func 
)
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>.

Returns
A SharedPtr to the posted task if allocation succeeded, or a null SharedPtr if allocation failed.

◆ Post() [2/3]

template<typename TaskType , typename... Args, typename = std::enable_if_t<std::is_base_of_v<Task, TaskType>>>
SharedPtr< TaskType > pw::async2::Dispatcher::Post ( Allocator allocator,
Args &&...  args 
)
inline

Allocates a TaskType using allocator and posts it to this execution context as with PostShared.

Returns
A SharedPtr to the posted task if allocation succeeded, or a null SharedPtr if allocation failed.

◆ Post() [3/3]

void pw::async2::Dispatcher::Post ( Task task)
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.

◆ PostFuture()

template<typename Fut >
SharedPtr< FutureTask< Fut > > pw::async2::Dispatcher::PostFuture ( Allocator allocator,
Fut &&  future 
)
inline

Allocates and posts a FutureTask that runs a future to completion.

Warning
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.
Returns
A SharedPtr to the posted task if allocation succeeded, or a null SharedPtr if allocation failed.

◆ PostShared()

template<typename T >
void pw::async2::Dispatcher::PostShared ( const SharedPtr< T > &  task)
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.

Precondition
task must NOT be nullptr.

◆ RunOnce()

template<typename Func >
SharedPtr< RunOnceTask< Func > > pw::async2::Dispatcher::RunOnce ( Allocator allocator,
Func &&  func 
)
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.

Warning
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.

◆ RunTask()

RunTaskResult pw::async2::Dispatcher::RunTask ( Task task)
inlineprotected

Runs the task that was returned from PopTaskToRun.

Warning
Do NOT access the 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.

The documentation for this class was generated from the following file: