1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-quickstart-guides: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker=================== 4*61c4878aSAndroid Build Coastguard WorkerQuickstart & guides 5*61c4878aSAndroid Build Coastguard Worker=================== 6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module-subpage:: 7*61c4878aSAndroid Build Coastguard Worker :name: pw_async2 8*61c4878aSAndroid Build Coastguard Worker 9*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides: 10*61c4878aSAndroid Build Coastguard Worker 11*61c4878aSAndroid Build Coastguard Worker------ 12*61c4878aSAndroid Build Coastguard WorkerGuides 13*61c4878aSAndroid Build Coastguard Worker------ 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard WorkerImplementing tasks 16*61c4878aSAndroid Build Coastguard Worker================== 17*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::Task` instances complete one or more asynchronous 18*61c4878aSAndroid Build Coastguard Workeroperations. They are the top-level "thread" primitives of ``pw_async2``. 19*61c4878aSAndroid Build Coastguard Worker 20*61c4878aSAndroid Build Coastguard WorkerYou can use one of the concrete subclasses of ``Task`` that Pigweed provides: 21*61c4878aSAndroid Build Coastguard Worker 22*61c4878aSAndroid Build Coastguard Worker* :cpp:class:`pw::async2::CoroOrElseTask`: Delegates to a provided 23*61c4878aSAndroid Build Coastguard Worker coroutine and executes an ``or_else`` handler function on failure. 24*61c4878aSAndroid Build Coastguard Worker* :cpp:class:`pw::async2::PendFuncTask`: Delegates to a provided 25*61c4878aSAndroid Build Coastguard Worker function. 26*61c4878aSAndroid Build Coastguard Worker* :cpp:class:`pw::async2::PendableAsTask`: Delegates to a type 27*61c4878aSAndroid Build Coastguard Worker with a :cpp:func:`pw::async2::Pend` method. 28*61c4878aSAndroid Build Coastguard Worker* :cpp:func:`pw::async2::AllocateTask`: Creates a concrete subclass of 29*61c4878aSAndroid Build Coastguard Worker ``Task``, just like ``PendableAsTask``, but the created task is 30*61c4878aSAndroid Build Coastguard Worker dynamically allocated and frees the associated memory upon 31*61c4878aSAndroid Build Coastguard Worker completion. 32*61c4878aSAndroid Build Coastguard Worker 33*61c4878aSAndroid Build Coastguard WorkerOr you can subclass ``Task`` yourself. See :cpp:class:`pw::async2::Task` 34*61c4878aSAndroid Build Coastguard Workerfor more guidance on subclassing. 35*61c4878aSAndroid Build Coastguard Worker 36*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-tasks: 37*61c4878aSAndroid Build Coastguard Worker 38*61c4878aSAndroid Build Coastguard WorkerHow a dispatcher manages tasks 39*61c4878aSAndroid Build Coastguard Worker============================== 40*61c4878aSAndroid Build Coastguard WorkerThe purpose of a :cpp:class:`pw::async2::Dispatcher` is to keep track of a set 41*61c4878aSAndroid Build Coastguard Workerof :cpp:class:`pw::async2::Task` objects and run them to completion. The 42*61c4878aSAndroid Build Coastguard Workerdispatcher is essentially a scheduler for cooperatively-scheduled 43*61c4878aSAndroid Build Coastguard Worker(non-preemptive) threads (tasks). 44*61c4878aSAndroid Build Coastguard Worker 45*61c4878aSAndroid Build Coastguard WorkerWhile a dispatcher is running, it waits for one or more tasks to waken and then 46*61c4878aSAndroid Build Coastguard Workeradvances each task by invoking its :cpp:func:`pw::async2::Task::DoPend` method. 47*61c4878aSAndroid Build Coastguard WorkerThe ``DoPend`` method is typically implemented manually by users, though it is 48*61c4878aSAndroid Build Coastguard Workerautomatically provided by coroutines. 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard WorkerIf the task is able to complete, ``DoPend`` will return ``Ready``, in which case 51*61c4878aSAndroid Build Coastguard Workerthe task is then deregistered from the dispatcher. 52*61c4878aSAndroid Build Coastguard Worker 53*61c4878aSAndroid Build Coastguard WorkerIf the task is unable to complete, ``DoPend`` must return ``Pending`` and arrange 54*61c4878aSAndroid Build Coastguard Workerfor the task to be woken up when it is able to make progress again. Once the 55*61c4878aSAndroid Build Coastguard Workertask is rewoken, the task is re-added to the ``Dispatcher`` queue. The 56*61c4878aSAndroid Build Coastguard Workerdispatcher will then invoke ``DoPend`` once more, continuing the cycle until 57*61c4878aSAndroid Build Coastguard Worker``DoPend`` returns ``Ready`` and the task is completed. 58*61c4878aSAndroid Build Coastguard Worker 59*61c4878aSAndroid Build Coastguard WorkerThe following sequence diagram summarizes the basic workflow: 60*61c4878aSAndroid Build Coastguard Worker 61*61c4878aSAndroid Build Coastguard Worker.. mermaid:: 62*61c4878aSAndroid Build Coastguard Worker 63*61c4878aSAndroid Build Coastguard Worker sequenceDiagram 64*61c4878aSAndroid Build Coastguard Worker participant e as External Event e.g. Interrupt 65*61c4878aSAndroid Build Coastguard Worker participant d as Dispatcher 66*61c4878aSAndroid Build Coastguard Worker participant t as Task 67*61c4878aSAndroid Build Coastguard Worker e->>t: Init Task 68*61c4878aSAndroid Build Coastguard Worker e->>d: Register task via Dispatcher::Post(Task) 69*61c4878aSAndroid Build Coastguard Worker d->>d: Add task to queue 70*61c4878aSAndroid Build Coastguard Worker d->>t: Run task via Task::DoPend() 71*61c4878aSAndroid Build Coastguard Worker t->>t: Task is waiting for data and can't yet complete 72*61c4878aSAndroid Build Coastguard Worker t->>e: Arrange for rewake via PW_ASYNC_STORE_WAKER 73*61c4878aSAndroid Build Coastguard Worker t->>d: Indicate that task is not complete via Pending() 74*61c4878aSAndroid Build Coastguard Worker d->>d: Remove task from queue 75*61c4878aSAndroid Build Coastguard Worker d->>d: Go to sleep because task queue is empty 76*61c4878aSAndroid Build Coastguard Worker e->>e: The data that the task needs has arrived 77*61c4878aSAndroid Build Coastguard Worker e->>d: Rewake via Waker::Wake() 78*61c4878aSAndroid Build Coastguard Worker d->>d: Re-add task to queue 79*61c4878aSAndroid Build Coastguard Worker d->>t: Run task via Task::DoPend() 80*61c4878aSAndroid Build Coastguard Worker t->>t: Task runs to completion 81*61c4878aSAndroid Build Coastguard Worker t->>d: Indicate that task is complete via Ready() 82*61c4878aSAndroid Build Coastguard Worker d->>d: Deregister the task 83*61c4878aSAndroid Build Coastguard Worker 84*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-pendables: 85*61c4878aSAndroid Build Coastguard Worker 86*61c4878aSAndroid Build Coastguard WorkerImplementing invariants for pendable functions 87*61c4878aSAndroid Build Coastguard Worker============================================== 88*61c4878aSAndroid Build Coastguard Worker.. _invariants: https://stackoverflow.com/a/112088 89*61c4878aSAndroid Build Coastguard Worker 90*61c4878aSAndroid Build Coastguard WorkerAny ``Pend``-like function or method similar to 91*61c4878aSAndroid Build Coastguard Worker:cpp:func:`pw::async2::Task::DoPend` that can pause when it's not able 92*61c4878aSAndroid Build Coastguard Workerto make progress on its task is known as a **pendable function**. When 93*61c4878aSAndroid Build Coastguard Workerimplementing a pendable function, make sure that you always uphold the 94*61c4878aSAndroid Build Coastguard Workerfollowing `invariants`_: 95*61c4878aSAndroid Build Coastguard Worker 96*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_async2-guides-pendables-incomplete` 97*61c4878aSAndroid Build Coastguard Worker* :ref:`module-pw_async2-guides-pendables-complete` 98*61c4878aSAndroid Build Coastguard Worker 99*61c4878aSAndroid Build Coastguard Worker.. note:: Exactly which APIs are considered pendable? 100*61c4878aSAndroid Build Coastguard Worker 101*61c4878aSAndroid Build Coastguard Worker If it has the signature ``(Context&, ...) -> Poll<T>``, 102*61c4878aSAndroid Build Coastguard Worker then it's a pendable function. 103*61c4878aSAndroid Build Coastguard Worker 104*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-pendables-incomplete: 105*61c4878aSAndroid Build Coastguard Worker 106*61c4878aSAndroid Build Coastguard WorkerArranging future completion of incomplete tasks 107*61c4878aSAndroid Build Coastguard Worker----------------------------------------------- 108*61c4878aSAndroid Build Coastguard WorkerWhen your pendable function can't yet complete: 109*61c4878aSAndroid Build Coastguard Worker 110*61c4878aSAndroid Build Coastguard Worker#. Do one of the following to make sure the task rewakes when it's ready to 111*61c4878aSAndroid Build Coastguard Worker make more progress: 112*61c4878aSAndroid Build Coastguard Worker 113*61c4878aSAndroid Build Coastguard Worker * Delegate waking to a subtask. Arrange for that subtask's 114*61c4878aSAndroid Build Coastguard Worker pendable function to wake this task when appropriate. 115*61c4878aSAndroid Build Coastguard Worker 116*61c4878aSAndroid Build Coastguard Worker * Arrange an external wakeup. Use :c:macro:`PW_ASYNC_STORE_WAKER` 117*61c4878aSAndroid Build Coastguard Worker to store the task's waker somewhere, and then call 118*61c4878aSAndroid Build Coastguard Worker :cpp:func:`pw::async2::Waker::Wake` from an interrupt or another thread 119*61c4878aSAndroid Build Coastguard Worker once the event that the task is waiting for has completed. 120*61c4878aSAndroid Build Coastguard Worker 121*61c4878aSAndroid Build Coastguard Worker * Re-enqueue the task with :cpp:func:`pw::async2::Context::ReEnqueue`. 122*61c4878aSAndroid Build Coastguard Worker This is a rare case. Usually, you should just create an immediately 123*61c4878aSAndroid Build Coastguard Worker invoked ``Waker``. 124*61c4878aSAndroid Build Coastguard Worker 125*61c4878aSAndroid Build Coastguard Worker#. Make sure to return :cpp:type:`pw::async2::Pending` to signal that the task 126*61c4878aSAndroid Build Coastguard Worker is incomplete. 127*61c4878aSAndroid Build Coastguard Worker 128*61c4878aSAndroid Build Coastguard WorkerIn other words, whenever your pendable function returns 129*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::async2::Pending`, you must guarantee that 130*61c4878aSAndroid Build Coastguard Worker:cpp:func:`pw::async2::Context::Wake` is called once in the future. 131*61c4878aSAndroid Build Coastguard Worker 132*61c4878aSAndroid Build Coastguard WorkerFor example, one implementation of a delayed task might arrange for its ``Waker`` 133*61c4878aSAndroid Build Coastguard Workerto be woken by a timer once some time has passed. Another case might be a 134*61c4878aSAndroid Build Coastguard Workermessaging library which calls ``Wake()`` on the receiving task once a sender has 135*61c4878aSAndroid Build Coastguard Workerplaced a message in a queue. 136*61c4878aSAndroid Build Coastguard Worker 137*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-pendables-complete: 138*61c4878aSAndroid Build Coastguard Worker 139*61c4878aSAndroid Build Coastguard WorkerCleaning up complete tasks 140*61c4878aSAndroid Build Coastguard Worker-------------------------- 141*61c4878aSAndroid Build Coastguard WorkerWhen your pendable function has completed, make sure to return 142*61c4878aSAndroid Build Coastguard Worker:cpp:type:`pw::async2::Ready` to signal that the task is complete. 143*61c4878aSAndroid Build Coastguard Worker 144*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-passing-data: 145*61c4878aSAndroid Build Coastguard Worker 146*61c4878aSAndroid Build Coastguard WorkerPassing data between tasks 147*61c4878aSAndroid Build Coastguard Worker========================== 148*61c4878aSAndroid Build Coastguard WorkerAstute readers will have noticed that the ``Wake`` method does not take any 149*61c4878aSAndroid Build Coastguard Workerarguments, and ``DoPoll`` does not provide the task being polled with any 150*61c4878aSAndroid Build Coastguard Workervalues! 151*61c4878aSAndroid Build Coastguard Worker 152*61c4878aSAndroid Build Coastguard WorkerUnlike callback-based interfaces, tasks (and the libraries they use) 153*61c4878aSAndroid Build Coastguard Workerare responsible for storage of the inputs and outputs of events. A common 154*61c4878aSAndroid Build Coastguard Workertechnique is for a task implementation to provide storage for outputs of an 155*61c4878aSAndroid Build Coastguard Workerevent. Then, upon completion of the event, the outputs will be stored in the 156*61c4878aSAndroid Build Coastguard Workertask before it is woken. The task will then be invoked again by the 157*61c4878aSAndroid Build Coastguard Workerdispatcher and can then operate on the resulting values. 158*61c4878aSAndroid Build Coastguard Worker 159*61c4878aSAndroid Build Coastguard WorkerThis common pattern is implemented by the 160*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::OnceSender` and 161*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::OnceReceiver` types (and their ``...Ref`` counterparts). 162*61c4878aSAndroid Build Coastguard WorkerThese interfaces allow a task to asynchronously wait for a value: 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard Worker.. tab-set:: 165*61c4878aSAndroid Build Coastguard Worker 166*61c4878aSAndroid Build Coastguard Worker .. tab-item:: Manual ``Task`` State Machine 167*61c4878aSAndroid Build Coastguard Worker 168*61c4878aSAndroid Build Coastguard Worker .. literalinclude:: examples/once_send_recv.cc 169*61c4878aSAndroid Build Coastguard Worker :language: cpp 170*61c4878aSAndroid Build Coastguard Worker :linenos: 171*61c4878aSAndroid Build Coastguard Worker :start-after: [pw_async2-examples-once-send-recv-manual] 172*61c4878aSAndroid Build Coastguard Worker :end-before: [pw_async2-examples-once-send-recv-manual] 173*61c4878aSAndroid Build Coastguard Worker 174*61c4878aSAndroid Build Coastguard Worker .. tab-item:: Coroutine Function 175*61c4878aSAndroid Build Coastguard Worker 176*61c4878aSAndroid Build Coastguard Worker .. literalinclude:: examples/once_send_recv.cc 177*61c4878aSAndroid Build Coastguard Worker :language: cpp 178*61c4878aSAndroid Build Coastguard Worker :linenos: 179*61c4878aSAndroid Build Coastguard Worker :start-after: [pw_async2-examples-once-send-recv-coro] 180*61c4878aSAndroid Build Coastguard Worker :end-before: [pw_async2-examples-once-send-recv-coro] 181*61c4878aSAndroid Build Coastguard Worker 182*61c4878aSAndroid Build Coastguard WorkerMore primitives (such as ``MultiSender`` and ``MultiReceiver``) are in-progress. 183*61c4878aSAndroid Build Coastguard WorkerUsers who find that they need other async primitives are encouraged to 184*61c4878aSAndroid Build Coastguard Workercontribute them upstream to ``pw::async2``! 185*61c4878aSAndroid Build Coastguard Worker 186*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-coroutines: 187*61c4878aSAndroid Build Coastguard Worker 188*61c4878aSAndroid Build Coastguard WorkerCoroutines 189*61c4878aSAndroid Build Coastguard Worker========== 190*61c4878aSAndroid Build Coastguard WorkerC++20 users can define tasks using coroutines! 191*61c4878aSAndroid Build Coastguard Worker 192*61c4878aSAndroid Build Coastguard Worker.. literalinclude:: examples/basic.cc 193*61c4878aSAndroid Build Coastguard Worker :language: cpp 194*61c4878aSAndroid Build Coastguard Worker :linenos: 195*61c4878aSAndroid Build Coastguard Worker :start-after: [pw_async2-examples-basic-coro] 196*61c4878aSAndroid Build Coastguard Worker :end-before: [pw_async2-examples-basic-coro] 197*61c4878aSAndroid Build Coastguard Worker 198*61c4878aSAndroid Build Coastguard WorkerAny value with a ``Poll<T> Pend(Context&)`` method can be passed to 199*61c4878aSAndroid Build Coastguard Worker``co_await``, which will return with a ``T`` when the result is ready. 200*61c4878aSAndroid Build Coastguard Worker 201*61c4878aSAndroid Build Coastguard WorkerTo return from a coroutine, ``co_return <expression>`` must be used instead of 202*61c4878aSAndroid Build Coastguard Workerthe usual ``return <expression>`` syntax. Because of this, the 203*61c4878aSAndroid Build Coastguard Worker:c:macro:`PW_TRY` and :c:macro:`PW_TRY_ASSIGN` macros are not usable within 204*61c4878aSAndroid Build Coastguard Workercoroutines. :c:macro:`PW_CO_TRY` and :c:macro:`PW_CO_TRY_ASSIGN` should be 205*61c4878aSAndroid Build Coastguard Workerused instead. 206*61c4878aSAndroid Build Coastguard Worker 207*61c4878aSAndroid Build Coastguard WorkerFor a more detailed explanation of Pigweed's coroutine support, see 208*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::Coro`. 209*61c4878aSAndroid Build Coastguard Worker 210*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-timing: 211*61c4878aSAndroid Build Coastguard Worker 212*61c4878aSAndroid Build Coastguard WorkerTiming 213*61c4878aSAndroid Build Coastguard Worker====== 214*61c4878aSAndroid Build Coastguard WorkerWhen using ``pw::async2``, timing functionality should be injected 215*61c4878aSAndroid Build Coastguard Workerby accepting a :cpp:class:`pw::async2::TimeProvider` (most commonly 216*61c4878aSAndroid Build Coastguard Worker``TimeProvider<SystemClock>`` when using the system's built-in ``time_point`` 217*61c4878aSAndroid Build Coastguard Workerand ``duration`` types). 218*61c4878aSAndroid Build Coastguard Worker 219*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::TimeProvider` allows for easily waiting 220*61c4878aSAndroid Build Coastguard Workerfor a timeout or deadline using the 221*61c4878aSAndroid Build Coastguard Worker:cpp:func:`pw::async2::TimePoint::WaitFor` and 222*61c4878aSAndroid Build Coastguard Worker:cpp:func:`pw::async2::TimePoint::WaitUntil` methods. 223*61c4878aSAndroid Build Coastguard Worker 224*61c4878aSAndroid Build Coastguard WorkerAdditionally, code which uses :cpp:class:`pw::async2::TimeProvider` for timing 225*61c4878aSAndroid Build Coastguard Workercan be tested with simulated time using 226*61c4878aSAndroid Build Coastguard Worker:cpp:class:`pw::async2::SimulatedTimeProvider`. Doing so helps avoid 227*61c4878aSAndroid Build Coastguard Workertiming-dependent test flakes and helps ensure that tests are fast since they 228*61c4878aSAndroid Build Coastguard Workerdon't need to wait for real-world time to elapse. 229*61c4878aSAndroid Build Coastguard Worker 230*61c4878aSAndroid Build Coastguard Worker.. _module-pw_async2-guides-faqs: 231*61c4878aSAndroid Build Coastguard Worker 232*61c4878aSAndroid Build Coastguard Worker--------------------------------- 233*61c4878aSAndroid Build Coastguard WorkerFrequently asked questions (FAQs) 234*61c4878aSAndroid Build Coastguard Worker--------------------------------- 235