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

Overview

A task which may complete one or more asynchronous operations.

The Task interface is commonly implemented by users wishing to schedule work on an asynchronous Dispatcher. To do this, users may subclass Task, providing an implementation of the DoPend method which advances the state of the Task as far as possible before yielding back to the Dispatcher.

This process works similarly to cooperatively-scheduled green threads or coroutines, with a Task representing a single logical "thread" of execution. Unlike some green thread or coroutine implementations, Task does not imply a separately-allocated stack: Task state is most commonly stored in fields of the Task subclass.

Once defined by a user, Tasks may be run by passing them to a Dispatcher via Dispatcher::Post. The Dispatcher will then Pend the Task every time that the Task indicates it is able to make progress.

Note that Task objects must not be destroyed while they are actively being Pend'd by a Dispatcher. To protect against this, be sure to do one of the following:

  • Use dynamic lifetimes by creating OwnedTask objects that continue to live until they receive a DoDestroy call.
  • Create Task objects whose stack-based lifetimes outlive their associated Dispatcher.
  • Call Deregister on the Task prior to its destruction. NOTE that Deregister may not be called from inside the Task's own Pend method.
Inheritance diagram for pw::async2::Task:
pw::containers::future::IntrusiveList< T >::Item pw::async2::CoroOrElseTask pw::async2::FutureCallbackTask< FutureType, Func > pw::async2::OwnedTask pw::async2::PendFuncTask< Func > pw::async2::PendableAsTask< Pendable > pw::async2::internal::PendableAsTaskWithOutput< Pendable > pw::async2::internal::AllocatedTask< Pendable > pw::async2::internal::RunHeapFuncTask< Func >

Public Member Functions

constexpr Task (log::Token name=kDefaultName)
 
 Task (const Task &)=delete
 
 Task (Task &&)=delete
 
Taskoperator= (const Task &)=delete
 
Taskoperator= (Task &&)=delete
 
virtual ~Task ()=default
 
Poll Pend (Context &cx)
 
bool IsRegistered () const
 
void Deregister ()
 

Private Member Functions

virtual Poll DoPend (Context &)=0
 

Friends

class Dispatcher
 
class OwnedTask
 
class Waker
 

Additional Inherited Members

- Protected Member Functions inherited from pw::containers::future::IntrusiveList< T >::Item
constexpr Item ()=default
 

Constructor & Destructor Documentation

◆ Task()

constexpr pw::async2::Task::Task ( log::Token  name = kDefaultName)
inlineexplicitconstexpr

Creates a task with the specified name. To generate a name token, use the PW_ASYNC_TASK_NAME macro, e.g.

class MyTask : public pw::async2::Task {
MyTask() : pw::async2::Task(PW_ASYNC_TASK_NAME("MyTask")) {}
};
Definition: task.h:62
#define PW_ASYNC_TASK_NAME(name)
Generates a token for use as a task name.
Definition: task.h:30
The Pigweed namespace.
Definition: alignment.h:27

◆ ~Task()

virtual pw::async2::Task::~Task ( )
virtualdefault

The task must not be registered with a Dispatcher upon destruction. Tasks are deregistered automatically upon completion or Dispatcher destruction.

This is necessary to ensure that neither the Dispatcher nor Waker reference the Task object after destruction.

The Task destructor cannot perform this deregistration. Other threads may be polling the task, and since the subclass destructor runs first, subclass state accessed by Pend would be invalidated before the base destructor could deregister the task.

Member Function Documentation

◆ Deregister()

void pw::async2::Task::Deregister ( )

Deregisters this Task from the linked Dispatcher and any associated Waker values.

This must not be invoked from inside this task's Pend function, as this will result in a deadlock.

Deregister will not destroy the underlying Task.

Note
If this task's Pend method is currently being run on the dispatcher, this method will block until Pend completes.
Warning
This method cannot guard against the dispatcher itself being destroyed, so this method must not be called concurrently with destruction of the dispatcher associated with this Task.

◆ DoPend()

virtual Poll pw::async2::Task::DoPend ( Context )
privatepure virtual

Attempts to advance this Task to completion.

This method should not perform synchronous waiting, as doing so may block the main Dispatcher loop and prevent other Task s from progressing. Because of this, Task s should not invoke blocking Dispatcher methods such as RunUntilComplete.

Tasks should also avoid invoking RunUntilStalled on their own Dispatcher.

Returns Ready if complete, or Pending if the Task was not yet able to complete.

If Pending is returned, the Task must ensure it is woken up when it is able to make progress. To do this, Task::Pend must arrange for Waker::Wake to be called, either by storing a copy of the Waker away to be awoken by another system (such as an interrupt handler).

Implemented in pw::async2::internal::RunHeapFuncTask< Func >, pw::async2::FutureCallbackTask< FutureType, Func >, pw::async2::CoroOrElseTask, pw::async2::internal::PendableAsTaskWithOutput< Pendable >, pw::async2::PendFuncTask< Func >, pw::async2::PendableAsTask< Pendable >, and pw::async2::internal::AllocatedTask< Pendable >.

◆ IsRegistered()

bool pw::async2::Task::IsRegistered ( ) const

Whether or not the Task is registered with a Dispatcher.

Returns true after this Task is passed to Dispatcher::Post until one of the following occurs:

◆ Pend()

Poll pw::async2::Task::Pend ( Context cx)
inline

A public interface for DoPend.

DoPend is normally invoked by a Dispatcher after a Task has been Post ed.

This wrapper should only be called by Task s delegating to other Task s. For example, a class MainTask might have separate fields for TaskA and TaskB, and could invoke Pend on these types within its own DoPend implementation.


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