1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker======== 4*61c4878aSAndroid Build Coastguard Workerpw_async 5*61c4878aSAndroid Build Coastguard Worker======== 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_async 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker-------- 10*61c4878aSAndroid Build Coastguard WorkerOverview 11*61c4878aSAndroid Build Coastguard Worker-------- 12*61c4878aSAndroid Build Coastguard WorkerPigweed's async module provides portable APIs and utilities for writing 13*61c4878aSAndroid Build Coastguard Workerasynchronous code. Currently, it provides: 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Worker- Message loop APIs 16*61c4878aSAndroid Build Coastguard Worker 17*61c4878aSAndroid Build Coastguard Worker.. attention:: 18*61c4878aSAndroid Build Coastguard Worker This module is still under construction. The API is not yet stable. 19*61c4878aSAndroid Build Coastguard Worker 20*61c4878aSAndroid Build Coastguard Worker---------- 21*61c4878aSAndroid Build Coastguard WorkerDispatcher 22*61c4878aSAndroid Build Coastguard Worker---------- 23*61c4878aSAndroid Build Coastguard WorkerDispatcher is an API for a message loop that schedules and executes Tasks. See 24*61c4878aSAndroid Build Coastguard Worker:bdg-ref-primary-line:`module-pw_async_basic` for an example implementation. 25*61c4878aSAndroid Build Coastguard Worker 26*61c4878aSAndroid Build Coastguard WorkerDispatcher is a pure virtual interface that is implemented by backends and 27*61c4878aSAndroid Build Coastguard WorkerFakeDispatcher. A virtual interface is used instead of a facade to allow 28*61c4878aSAndroid Build Coastguard Workersubstituting a FakeDispatcher for a Dispatcher backend in tests. 29*61c4878aSAndroid Build Coastguard Worker 30*61c4878aSAndroid Build Coastguard WorkerDispatcher API 31*61c4878aSAndroid Build Coastguard Worker============== 32*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::async::Dispatcher 33*61c4878aSAndroid Build Coastguard Worker :members: 34*61c4878aSAndroid Build Coastguard Worker 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard WorkerTask API 37*61c4878aSAndroid Build Coastguard Worker============== 38*61c4878aSAndroid Build Coastguard Worker.. doxygenstruct:: pw::async::Context 39*61c4878aSAndroid Build Coastguard Worker :members: 40*61c4878aSAndroid Build Coastguard Worker 41*61c4878aSAndroid Build Coastguard Worker.. doxygentypedef:: pw::async::TaskFunction 42*61c4878aSAndroid Build Coastguard Worker 43*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::async::Task 44*61c4878aSAndroid Build Coastguard Worker :members: 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard WorkerFacade API 47*61c4878aSAndroid Build Coastguard Worker========== 48*61c4878aSAndroid Build Coastguard Worker 49*61c4878aSAndroid Build Coastguard WorkerTask 50*61c4878aSAndroid Build Coastguard Worker---- 51*61c4878aSAndroid Build Coastguard WorkerThe ``Task`` type represents a work item that can be submitted to and executed 52*61c4878aSAndroid Build Coastguard Workerby a ``Dispatcher``. 53*61c4878aSAndroid Build Coastguard Worker 54*61c4878aSAndroid Build Coastguard WorkerTo run work on a ``Dispatcher`` event loop, a ``Task`` can be constructed from 55*61c4878aSAndroid Build Coastguard Workera function or lambda (see ``pw::async::TaskFunction``) and submitted to run 56*61c4878aSAndroid Build Coastguard Workerusing the ``pw::async::Dispatcher::Post`` method (and its siblings, ``PostAt`` 57*61c4878aSAndroid Build Coastguard Workeretc.). 58*61c4878aSAndroid Build Coastguard Worker 59*61c4878aSAndroid Build Coastguard WorkerThe ``Task`` facade enables backends to provide custom storage containers for 60*61c4878aSAndroid Build Coastguard Worker``Task`` s, as well as to keep per- ``Task`` data alongside the ``TaskFunction`` 61*61c4878aSAndroid Build Coastguard Worker(such as ``next`` pointers for intrusive linked-lists of ``Task``). 62*61c4878aSAndroid Build Coastguard Worker 63*61c4878aSAndroid Build Coastguard WorkerThe active Task backend is configured with the GN variable 64*61c4878aSAndroid Build Coastguard Worker``pw_async_TASK_BACKEND``. The specified target must define a class 65*61c4878aSAndroid Build Coastguard Worker``pw::async::backend::NativeTask`` in the header ``pw_async_backend/task.h`` 66*61c4878aSAndroid Build Coastguard Workerthat meets the interface requirements in ``public/pw_async/task.h``. Task will 67*61c4878aSAndroid Build Coastguard Workerthen trivially wrap ``NativeTask``. 68*61c4878aSAndroid Build Coastguard Worker 69*61c4878aSAndroid Build Coastguard WorkerThe bazel build provides the ``pw_async_task_backend`` label flag to configure 70*61c4878aSAndroid Build Coastguard Workerthe active Task backend. 71*61c4878aSAndroid Build Coastguard Worker 72*61c4878aSAndroid Build Coastguard WorkerFakeDispatcher 73*61c4878aSAndroid Build Coastguard Worker-------------- 74*61c4878aSAndroid Build Coastguard WorkerThe FakeDispatcher facade is a utility for simulating a real Dispatcher 75*61c4878aSAndroid Build Coastguard Workerin tests. FakeDispatcher simulates time to allow for reliable, fast testing of 76*61c4878aSAndroid Build Coastguard Workercode that uses Dispatcher. FakeDispatcher is a facade instead of a concrete 77*61c4878aSAndroid Build Coastguard Workerimplementation because it depends on Task state for processing tasks, which 78*61c4878aSAndroid Build Coastguard Workervaries across Task backends. 79*61c4878aSAndroid Build Coastguard Worker 80*61c4878aSAndroid Build Coastguard WorkerThe active FakeDispatcher backend is configured with the GN variable 81*61c4878aSAndroid Build Coastguard Worker``pw_async_FAKE_DISPATCHER_BACKEND``. The specified target must define a class 82*61c4878aSAndroid Build Coastguard Worker``pw::async::test::backend::NativeFakeDispatcher`` in the header 83*61c4878aSAndroid Build Coastguard Worker``pw_async_backend/fake_dispatcher.h`` that meets the interface requirements in 84*61c4878aSAndroid Build Coastguard Worker``public/pw_async/task.h``. FakeDispatcher will then trivially wrap 85*61c4878aSAndroid Build Coastguard Worker``NativeFakeDispatcher``. 86*61c4878aSAndroid Build Coastguard Worker 87*61c4878aSAndroid Build Coastguard WorkerThe bazel build provides the ``pw_async_fake_dispatcher_backend`` label flag to 88*61c4878aSAndroid Build Coastguard Workerconfigure the FakeDispatcher backend. 89*61c4878aSAndroid Build Coastguard Worker 90*61c4878aSAndroid Build Coastguard WorkerTesting FakeDispatcher 91*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^ 92*61c4878aSAndroid Build Coastguard WorkerThe GN template ``fake_dispatcher_tests`` in ``fake_dispatcher_tests.gni`` 93*61c4878aSAndroid Build Coastguard Workercreates a test target that tests a FakeDispatcher backend. This enables 94*61c4878aSAndroid Build Coastguard Workerone test suite to be shared across FakeDispatcher backends and ensures 95*61c4878aSAndroid Build Coastguard Workerconformance. 96*61c4878aSAndroid Build Coastguard Worker 97*61c4878aSAndroid Build Coastguard WorkerFunctionDispatcher 98*61c4878aSAndroid Build Coastguard Worker------------------ 99*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::async::FunctionDispatcher 100*61c4878aSAndroid Build Coastguard Worker :members: 101*61c4878aSAndroid Build Coastguard Worker 102*61c4878aSAndroid Build Coastguard WorkerHeapDispatcher 103*61c4878aSAndroid Build Coastguard Worker-------------- 104*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::async::HeapDispatcher 105*61c4878aSAndroid Build Coastguard Worker :members: 106*61c4878aSAndroid Build Coastguard Worker 107*61c4878aSAndroid Build Coastguard WorkerDesign 108*61c4878aSAndroid Build Coastguard Worker====== 109*61c4878aSAndroid Build Coastguard Worker 110*61c4878aSAndroid Build Coastguard WorkerTask Ownership 111*61c4878aSAndroid Build Coastguard Worker-------------- 112*61c4878aSAndroid Build Coastguard WorkerTasks are owned by clients rather than the Dispatcher. This avoids either 113*61c4878aSAndroid Build Coastguard Workermemory allocation or queue size limits in Dispatcher implementations. However, 114*61c4878aSAndroid Build Coastguard Workercare must be taken that clients do not destroy Tasks before they have been 115*61c4878aSAndroid Build Coastguard Workerexecuted or canceled. 116*61c4878aSAndroid Build Coastguard Worker 117*61c4878aSAndroid Build Coastguard WorkerGetting Started 118*61c4878aSAndroid Build Coastguard Worker=============== 119*61c4878aSAndroid Build Coastguard WorkerFirst, configure the Task backend for the Dispatcher backend you will be using: 120*61c4878aSAndroid Build Coastguard Worker 121*61c4878aSAndroid Build Coastguard Worker.. code-block:: 122*61c4878aSAndroid Build Coastguard Worker 123*61c4878aSAndroid Build Coastguard Worker pw_async_TASK_BACKEND = "$dir_pw_async_basic:task" 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard Worker 126*61c4878aSAndroid Build Coastguard WorkerNext, create an executable target that depends on the Dispatcher backend you 127*61c4878aSAndroid Build Coastguard Workerwant to use: 128*61c4878aSAndroid Build Coastguard Worker 129*61c4878aSAndroid Build Coastguard Worker.. code-block:: 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard Worker pw_executable("hello_world") { 132*61c4878aSAndroid Build Coastguard Worker sources = [ "main.cc" ] 133*61c4878aSAndroid Build Coastguard Worker deps = [ "$dir_pw_async_basic:dispatcher" ] 134*61c4878aSAndroid Build Coastguard Worker } 135*61c4878aSAndroid Build Coastguard Worker 136*61c4878aSAndroid Build Coastguard WorkerNext, instantiate the Dispatcher and post a task: 137*61c4878aSAndroid Build Coastguard Worker 138*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 139*61c4878aSAndroid Build Coastguard Worker 140*61c4878aSAndroid Build Coastguard Worker #include "pw_async_basic/dispatcher.h" 141*61c4878aSAndroid Build Coastguard Worker 142*61c4878aSAndroid Build Coastguard Worker int main() { 143*61c4878aSAndroid Build Coastguard Worker BasicDispatcher dispatcher; 144*61c4878aSAndroid Build Coastguard Worker 145*61c4878aSAndroid Build Coastguard Worker // Spawn a thread for the dispatcher to run on. 146*61c4878aSAndroid Build Coastguard Worker Thread work_thread(thread::stl::Options(), dispatcher); 147*61c4878aSAndroid Build Coastguard Worker 148*61c4878aSAndroid Build Coastguard Worker Task task([](pw::async::Context& ctx){ 149*61c4878aSAndroid Build Coastguard Worker printf("hello world\n"); 150*61c4878aSAndroid Build Coastguard Worker ctx.dispatcher->RequestStop(); 151*61c4878aSAndroid Build Coastguard Worker }); 152*61c4878aSAndroid Build Coastguard Worker 153*61c4878aSAndroid Build Coastguard Worker // Execute `task` in 5 seconds. 154*61c4878aSAndroid Build Coastguard Worker dispatcher.PostAfter(task, 5s); 155*61c4878aSAndroid Build Coastguard Worker 156*61c4878aSAndroid Build Coastguard Worker // Blocks until `task` runs. 157*61c4878aSAndroid Build Coastguard Worker work_thread.join(); 158*61c4878aSAndroid Build Coastguard Worker return 0; 159*61c4878aSAndroid Build Coastguard Worker } 160*61c4878aSAndroid Build Coastguard Worker 161*61c4878aSAndroid Build Coastguard WorkerThe above example runs the dispatcher on a new thread, but it can also run on 162*61c4878aSAndroid Build Coastguard Workerthe current/main thread: 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker #include "pw_async_basic/dispatcher.h" 167*61c4878aSAndroid Build Coastguard Worker 168*61c4878aSAndroid Build Coastguard Worker int main() { 169*61c4878aSAndroid Build Coastguard Worker BasicDispatcher dispatcher; 170*61c4878aSAndroid Build Coastguard Worker 171*61c4878aSAndroid Build Coastguard Worker Task task([](pw::async::Context& ctx){ 172*61c4878aSAndroid Build Coastguard Worker printf("hello world\n"); 173*61c4878aSAndroid Build Coastguard Worker }); 174*61c4878aSAndroid Build Coastguard Worker 175*61c4878aSAndroid Build Coastguard Worker // Execute `task` in 5 seconds. 176*61c4878aSAndroid Build Coastguard Worker dispatcher.PostAfter(task, 5s); 177*61c4878aSAndroid Build Coastguard Worker 178*61c4878aSAndroid Build Coastguard Worker dispatcher.Run(); 179*61c4878aSAndroid Build Coastguard Worker return 0; 180*61c4878aSAndroid Build Coastguard Worker } 181*61c4878aSAndroid Build Coastguard Worker 182*61c4878aSAndroid Build Coastguard WorkerFake Dispatcher 183*61c4878aSAndroid Build Coastguard Worker=============== 184*61c4878aSAndroid Build Coastguard WorkerTo test async code, FakeDispatcher should be dependency injected in place of 185*61c4878aSAndroid Build Coastguard WorkerDispatcher. Then, time should be driven in unit tests using the ``Run*()`` 186*61c4878aSAndroid Build Coastguard Workermethods. For convenience, you can use the test fixture 187*61c4878aSAndroid Build Coastguard WorkerFakeDispatcherFixture. 188*61c4878aSAndroid Build Coastguard Worker 189*61c4878aSAndroid Build Coastguard Worker.. doxygenclass:: pw::async::test::FakeDispatcherFixture 190*61c4878aSAndroid Build Coastguard Worker :members: 191*61c4878aSAndroid Build Coastguard Worker 192*61c4878aSAndroid Build Coastguard Worker.. attention:: 193*61c4878aSAndroid Build Coastguard Worker 194*61c4878aSAndroid Build Coastguard Worker ``FakeDispatcher::now()`` will return the simulated time. 195*61c4878aSAndroid Build Coastguard Worker ``Dispatcher::now()`` should therefore be used to get the current time in 196*61c4878aSAndroid Build Coastguard Worker async code instead of other sources of time to ensure consistent time values 197*61c4878aSAndroid Build Coastguard Worker and reliable tests. 198*61c4878aSAndroid Build Coastguard Worker 199*61c4878aSAndroid Build Coastguard Worker------- 200*61c4878aSAndroid Build Coastguard WorkerRoadmap 201*61c4878aSAndroid Build Coastguard Worker------- 202*61c4878aSAndroid Build Coastguard Worker- Stabilize Task cancellation API 203*61c4878aSAndroid Build Coastguard Worker- Utility for dynamically allocated Tasks 204*61c4878aSAndroid Build Coastguard Worker- CMake support 205*61c4878aSAndroid Build Coastguard Worker- Support for C++20 coroutines 206*61c4878aSAndroid Build Coastguard Worker 207*61c4878aSAndroid Build Coastguard Worker.. toctree:: 208*61c4878aSAndroid Build Coastguard Worker :hidden: 209*61c4878aSAndroid Build Coastguard Worker :maxdepth: 1 210*61c4878aSAndroid Build Coastguard Worker 211*61c4878aSAndroid Build Coastguard Worker Backends <backends> 212