1*61c4878aSAndroid Build Coastguard Worker.. _seed-0112: 2*61c4878aSAndroid Build Coastguard Worker 3*61c4878aSAndroid Build Coastguard Worker====================== 4*61c4878aSAndroid Build Coastguard Worker0112: Async Poll Model 5*61c4878aSAndroid Build Coastguard Worker====================== 6*61c4878aSAndroid Build Coastguard Worker.. seed:: 7*61c4878aSAndroid Build Coastguard Worker :number: 0112 8*61c4878aSAndroid Build Coastguard Worker :name: Async Poll Model 9*61c4878aSAndroid Build Coastguard Worker :status: Accepted 10*61c4878aSAndroid Build Coastguard Worker :proposal_date: 2023-9-19 11*61c4878aSAndroid Build Coastguard Worker :cl: 168337 12*61c4878aSAndroid Build Coastguard Worker :authors: Taylor Cramer 13*61c4878aSAndroid Build Coastguard Worker :facilitator: Wyatt Hepler 14*61c4878aSAndroid Build Coastguard Worker 15*61c4878aSAndroid Build Coastguard Worker------- 16*61c4878aSAndroid Build Coastguard WorkerSummary 17*61c4878aSAndroid Build Coastguard Worker------- 18*61c4878aSAndroid Build Coastguard WorkerThis SEED proposes the development of a new “informed-Poll”-based pw::async 19*61c4878aSAndroid Build Coastguard Workerlibrary. The “informed Poll” model, popularized by 20*61c4878aSAndroid Build Coastguard Worker`Rust’s Future trait, <https://doc.rust-lang.org/std/future/trait.Future.html>`_ 21*61c4878aSAndroid Build Coastguard Workeroffers an alternative to callback-based APIs. Rather than invoking a separate 22*61c4878aSAndroid Build Coastguard Workercallback for every event, the informed Poll model runs asynchronous ``Task`` s. 23*61c4878aSAndroid Build Coastguard Worker 24*61c4878aSAndroid Build Coastguard WorkerA ``Task`` is an asynchronous unit of work. Informed Poll-based asynchronous 25*61c4878aSAndroid Build Coastguard Workersystems use ``Task`` s similar to how synchronous systems use threads. 26*61c4878aSAndroid Build Coastguard WorkerUsers implement the ``Poll`` function of a ``Task`` in order to define the 27*61c4878aSAndroid Build Coastguard Workerasynchronous behavior of a routine. 28*61c4878aSAndroid Build Coastguard Worker 29*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 30*61c4878aSAndroid Build Coastguard Worker 31*61c4878aSAndroid Build Coastguard Worker class Task { 32*61c4878aSAndroid Build Coastguard Worker public: 33*61c4878aSAndroid Build Coastguard Worker /// Does some work, returning ``Complete`` if done. 34*61c4878aSAndroid Build Coastguard Worker /// If not complete, returns ``Pending`` and arranges for `cx.waker()` to be 35*61c4878aSAndroid Build Coastguard Worker /// awoken when `Task:Poll` should be invoked again. 36*61c4878aSAndroid Build Coastguard Worker virtual pw::MaybeReady<Complete> Poll(pw::async::Context& cx); 37*61c4878aSAndroid Build Coastguard Worker }; 38*61c4878aSAndroid Build Coastguard Worker 39*61c4878aSAndroid Build Coastguard WorkerUsers can start running a ``Task`` by ``Post`` ing it to a ``Dispatcher``. 40*61c4878aSAndroid Build Coastguard Worker``Dispatcher`` s are asynchronous event loops which are responsible for calling 41*61c4878aSAndroid Build Coastguard Worker``Poll`` every time the ``Task`` indicates that it is ready to make progress. 42*61c4878aSAndroid Build Coastguard Worker 43*61c4878aSAndroid Build Coastguard WorkerThis API structure allows Pigweed async code to operate efficiently, with low 44*61c4878aSAndroid Build Coastguard Workermemory overhead, zero dynamic allocations, and simpler state management. 45*61c4878aSAndroid Build Coastguard Worker 46*61c4878aSAndroid Build Coastguard WorkerPigweed’s new async APIs will enable multi-step asynchronous operations without 47*61c4878aSAndroid Build Coastguard Workerqueuing multiple callbacks. Here is an example in which a proxy object receives 48*61c4878aSAndroid Build Coastguard Workerdata and then sends it out before completing: 49*61c4878aSAndroid Build Coastguard Worker 50*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 51*61c4878aSAndroid Build Coastguard Worker 52*61c4878aSAndroid Build Coastguard Worker class ProxyOneMessage : public Task { 53*61c4878aSAndroid Build Coastguard Worker public: 54*61c4878aSAndroid Build Coastguard Worker /// Proxies one ``Data`` packet from a ``Receiver`` to a ``Sender``. 55*61c4878aSAndroid Build Coastguard Worker /// 56*61c4878aSAndroid Build Coastguard Worker /// Returns: 57*61c4878aSAndroid Build Coastguard Worker /// ``pw::async::Complete`` when the task has completed. This happens 58*61c4878aSAndroid Build Coastguard Worker /// after a ``Data`` packet has been received and sent, or an error 59*61c4878aSAndroid Build Coastguard Worker /// has occurred and been logged. 60*61c4878aSAndroid Build Coastguard Worker /// ``pw::async::Pending`` if unable to complete. ``cx.waker()`` will be 61*61c4878aSAndroid Build Coastguard Worker /// awoken when ``Poll`` should be re-invoked. 62*61c4878aSAndroid Build Coastguard Worker pw::async::MaybeReady<pw::async::Complete> Poll(pw::async::Context& cx) { 63*61c4878aSAndroid Build Coastguard Worker if (!send_future_) { 64*61c4878aSAndroid Build Coastguard Worker // ``PollRead`` checks for available data or errors. 65*61c4878aSAndroid Build Coastguard Worker pw::async::MaybeReady<pw::Result<Data>> new_data = receiver_.PollRead(cx); 66*61c4878aSAndroid Build Coastguard Worker if (new_data.is_pending()) { 67*61c4878aSAndroid Build Coastguard Worker return pw::async::Pending; 68*61c4878aSAndroid Build Coastguard Worker } 69*61c4878aSAndroid Build Coastguard Worker if (!new_data->ok()) { 70*61c4878aSAndroid Build Coastguard Worker PW_LOG_ERROR("Receiving failed: %s", data->status().str()); 71*61c4878aSAndroid Build Coastguard Worker return pw::async::Complete; 72*61c4878aSAndroid Build Coastguard Worker } 73*61c4878aSAndroid Build Coastguard Worker Data& data = **new_data; 74*61c4878aSAndroid Build Coastguard Worker send_future_ = sender_.Send(std::move(data)); 75*61c4878aSAndroid Build Coastguard Worker } 76*61c4878aSAndroid Build Coastguard Worker // ``PollSend`` attempts to send `data_`, returning `Pending` if 77*61c4878aSAndroid Build Coastguard Worker // `sender_` was not yet able to accept `data_`. 78*61c4878aSAndroid Build Coastguard Worker pw::async::MaybeReady<pw::Status> sent = send_future_.Poll(cx); 79*61c4878aSAndroid Build Coastguard Worker if (sent.is_pending()) { 80*61c4878aSAndroid Build Coastguard Worker return pw::async::Pending; 81*61c4878aSAndroid Build Coastguard Worker } 82*61c4878aSAndroid Build Coastguard Worker if (!sent->ok()) { 83*61c4878aSAndroid Build Coastguard Worker PW_LOG_ERROR("Sending failed: %s", sent->str()); 84*61c4878aSAndroid Build Coastguard Worker } 85*61c4878aSAndroid Build Coastguard Worker return pw::async::Complete; 86*61c4878aSAndroid Build Coastguard Worker } 87*61c4878aSAndroid Build Coastguard Worker 88*61c4878aSAndroid Build Coastguard Worker private: 89*61c4878aSAndroid Build Coastguard Worker // ``SendFuture`` is some type returned by `Sender::Send` that offers a 90*61c4878aSAndroid Build Coastguard Worker // ``Poll`` method similar to the one on ``Task``. 91*61c4878aSAndroid Build Coastguard Worker std::optional<SendFuture> send_future_; 92*61c4878aSAndroid Build Coastguard Worker // `receiver_` and `sender_` are provided by the `ProxyOneMessage` constructor. 93*61c4878aSAndroid Build Coastguard Worker Receiver receiver_; 94*61c4878aSAndroid Build Coastguard Worker Sender sender_; 95*61c4878aSAndroid Build Coastguard Worker }; 96*61c4878aSAndroid Build Coastguard Worker 97*61c4878aSAndroid Build Coastguard Worker // --- Usage --- 98*61c4878aSAndroid Build Coastguard Worker // ``static`` is used for simplicity, but real ``Task`` s can have temporary 99*61c4878aSAndroid Build Coastguard Worker // lifetimes. 100*61c4878aSAndroid Build Coastguard Worker static ProxyOneMessage proxy(receiver, sender); 101*61c4878aSAndroid Build Coastguard Worker 102*61c4878aSAndroid Build Coastguard Worker // Runs `proxy` until it completes, either by successfully receiving and 103*61c4878aSAndroid Build Coastguard Worker // sending a message, or by exiting early after logging an error. 104*61c4878aSAndroid Build Coastguard Worker dispatcher.Post(proxy); 105*61c4878aSAndroid Build Coastguard Worker 106*61c4878aSAndroid Build Coastguard Worker-------- 107*61c4878aSAndroid Build Coastguard WorkerProposal 108*61c4878aSAndroid Build Coastguard Worker-------- 109*61c4878aSAndroid Build Coastguard WorkerThis SEED proposes that Pigweed develop a set of async APIs and utilities 110*61c4878aSAndroid Build Coastguard Workerdesigned around the informed Poll model. If early trials with partner teams are 111*61c4878aSAndroid Build Coastguard Workersuccessful, this new library will be used as the basis for future async code in 112*61c4878aSAndroid Build Coastguard WorkerPigweed. 113*61c4878aSAndroid Build Coastguard Worker 114*61c4878aSAndroid Build Coastguard Worker----- 115*61c4878aSAndroid Build Coastguard WorkerGoals 116*61c4878aSAndroid Build Coastguard Worker----- 117*61c4878aSAndroid Build Coastguard WorkerThe goals of this SEED are as follows: 118*61c4878aSAndroid Build Coastguard Worker 119*61c4878aSAndroid Build Coastguard Worker* Establish community consensus that informed ``Poll`` is the best async model 120*61c4878aSAndroid Build Coastguard Worker for Pigweed to pursue. 121*61c4878aSAndroid Build Coastguard Worker* Outline an initial API for ``Dispatcher`` implementors (platform authors) and 122*61c4878aSAndroid Build Coastguard Worker top-level ``Task`` writers. 123*61c4878aSAndroid Build Coastguard Worker 124*61c4878aSAndroid Build Coastguard Worker---------- 125*61c4878aSAndroid Build Coastguard WorkerMotivation 126*61c4878aSAndroid Build Coastguard Worker---------- 127*61c4878aSAndroid Build Coastguard WorkerThe purpose of this SEED is to gather agreement that ``Poll``-based async 128*61c4878aSAndroid Build Coastguard WorkerAPIs are worth pursuing. We believe that these APIs provide the needed support 129*61c4878aSAndroid Build Coastguard Workerfor: 130*61c4878aSAndroid Build Coastguard Worker 131*61c4878aSAndroid Build Coastguard Worker* Small code size 132*61c4878aSAndroid Build Coastguard Worker* Environments without dynamic allocation 133*61c4878aSAndroid Build Coastguard Worker* Creating reusable building blocks and high-level modules 134*61c4878aSAndroid Build Coastguard Worker 135*61c4878aSAndroid Build Coastguard WorkerThe current ``Task`` API is limited in these respects: a single ``Task`` must 136*61c4878aSAndroid Build Coastguard Workerbe created and stored for every individual asynchronous event. ``Task`` s 137*61c4878aSAndroid Build Coastguard Workercannot be reused, and the memory allocated for a ``Task`` can only be reclaimed 138*61c4878aSAndroid Build Coastguard Workerafter a ``Task`` has been completed or cancelled, resulting in complex 139*61c4878aSAndroid Build Coastguard Workersemantics for multithreaded environments or those with interrupt-driven events. 140*61c4878aSAndroid Build Coastguard Worker 141*61c4878aSAndroid Build Coastguard WorkerCompleting a sequence of events therefore requires either dynamic allocation 142*61c4878aSAndroid Build Coastguard Workeror statically saving a separate ``Task`` worth of memory for every kind of 143*61c4878aSAndroid Build Coastguard Workerevent that may occur. 144*61c4878aSAndroid Build Coastguard Worker 145*61c4878aSAndroid Build Coastguard WorkerAdditionally, every asynchronous layer requires introducing another round of 146*61c4878aSAndroid Build Coastguard Workercallbacks whose semantics may be unclear and whose captures may add lifetime 147*61c4878aSAndroid Build Coastguard Workerchallenges. 148*61c4878aSAndroid Build Coastguard Worker 149*61c4878aSAndroid Build Coastguard WorkerThis proposal resolves these issues by choosing an alternative approach. 150*61c4878aSAndroid Build Coastguard Worker 151*61c4878aSAndroid Build Coastguard Worker----------- 152*61c4878aSAndroid Build Coastguard WorkerAPI Summary 153*61c4878aSAndroid Build Coastguard Worker----------- 154*61c4878aSAndroid Build Coastguard Worker 155*61c4878aSAndroid Build Coastguard WorkerA Note On Specificity 156*61c4878aSAndroid Build Coastguard Worker===================== 157*61c4878aSAndroid Build Coastguard WorkerThis SEED provides API outlines in order to more clearly explain the intended 158*61c4878aSAndroid Build Coastguard WorkerAPI direction. The specific function signatures shown here are not meant to be 159*61c4878aSAndroid Build Coastguard Workerauthoritative, and are subject to change. As the implementation develops 160*61c4878aSAndroid Build Coastguard Workersupport for more platforms and features, some additions, changes, or removals 161*61c4878aSAndroid Build Coastguard Workermay be necessary and will be considered as part of the regular CL review 162*61c4878aSAndroid Build Coastguard Workerprocess. 163*61c4878aSAndroid Build Coastguard Worker 164*61c4878aSAndroid Build Coastguard WorkerWith that in mind, asynchronous ``Task`` s in this model could adopt an API 165*61c4878aSAndroid Build Coastguard Workerlike the following: 166*61c4878aSAndroid Build Coastguard Worker 167*61c4878aSAndroid Build Coastguard WorkerThe ``MaybeReady`` Type 168*61c4878aSAndroid Build Coastguard Worker======================= 169*61c4878aSAndroid Build Coastguard WorkerFunctions return ``MaybeReady<T>`` to indicate that their result may or may 170*61c4878aSAndroid Build Coastguard Workernot be available yet. ``MaybeReady<T>`` is a generic sum type similar to 171*61c4878aSAndroid Build Coastguard Worker``std::optional<T>``. It has two variants, ``Ready(T)`` or ``Pending``. 172*61c4878aSAndroid Build Coastguard Worker 173*61c4878aSAndroid Build Coastguard WorkerThe API is similar to ``std::optional<T>``, but ``MaybeReady<T>`` provides extra 174*61c4878aSAndroid Build Coastguard Workersemantic clarification that the absense of a value means that it is not ready 175*61c4878aSAndroid Build Coastguard Workeryet. 176*61c4878aSAndroid Build Coastguard Worker 177*61c4878aSAndroid Build Coastguard WorkerPaired with the ``Complete`` type, ``MaybeReady<Complete>`` acts like 178*61c4878aSAndroid Build Coastguard Worker``bool IsComplete``, but provides more semantic information to the user than 179*61c4878aSAndroid Build Coastguard Workerreturning a simple ``bool``. 180*61c4878aSAndroid Build Coastguard Worker 181*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 182*61c4878aSAndroid Build Coastguard Worker 183*61c4878aSAndroid Build Coastguard Worker /// A value that is ready, and 184*61c4878aSAndroid Build Coastguard Worker template<typename T> 185*61c4878aSAndroid Build Coastguard Worker struct Ready<T> { value: T }; 186*61c4878aSAndroid Build Coastguard Worker 187*61c4878aSAndroid Build Coastguard Worker /// A content-less struct that indicates a not-ready value. 188*61c4878aSAndroid Build Coastguard Worker struct Pending {}; 189*61c4878aSAndroid Build Coastguard Worker 190*61c4878aSAndroid Build Coastguard Worker /// A value of type `T` that is possibly available. 191*61c4878aSAndroid Build Coastguard Worker /// 192*61c4878aSAndroid Build Coastguard Worker /// This is similar to ``std::optional<T>``, but provides additional 193*61c4878aSAndroid Build Coastguard Worker /// semantic indication that the value is not ready yet (still pending). 194*61c4878aSAndroid Build Coastguard Worker /// This can aid in making type signatures such as 195*61c4878aSAndroid Build Coastguard Worker /// ``MaybeReady<std::optional<Item>>`` easier to understand, and provides 196*61c4878aSAndroid Build Coastguard Worker /// clearer naming like `IsReady` (compared to ``has_value()``). 197*61c4878aSAndroid Build Coastguard Worker template<typename T> 198*61c4878aSAndroid Build Coastguard Worker class MaybeReady { 199*61c4878aSAndroid Build Coastguard Worker public: 200*61c4878aSAndroid Build Coastguard Worker /// Implicitly converts from ``T``, ``Ready<T>`` or ``Pending``. 201*61c4878aSAndroid Build Coastguard Worker MaybeReady(T); 202*61c4878aSAndroid Build Coastguard Worker MaybeReady(Ready<T>); 203*61c4878aSAndroid Build Coastguard Worker MaybeReady(Pending); 204*61c4878aSAndroid Build Coastguard Worker bool IsReady(); 205*61c4878aSAndroid Build Coastguard Worker T Value() &&; 206*61c4878aSAndroid Build Coastguard Worker ... 207*61c4878aSAndroid Build Coastguard Worker }; 208*61c4878aSAndroid Build Coastguard Worker 209*61c4878aSAndroid Build Coastguard Worker /// A content-less struct that indicates completion. 210*61c4878aSAndroid Build Coastguard Worker struct Complete {}; 211*61c4878aSAndroid Build Coastguard Worker 212*61c4878aSAndroid Build Coastguard WorkerNote that the ``Pending`` type takes no type arguments, and so can be created 213*61c4878aSAndroid Build Coastguard Workerand returned from macros that don't know which ``T`` is returned by the 214*61c4878aSAndroid Build Coastguard Workerfunction they are in. For example: 215*61c4878aSAndroid Build Coastguard Worker 216*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 217*61c4878aSAndroid Build Coastguard Worker 218*61c4878aSAndroid Build Coastguard Worker // Simplified assignment macro 219*61c4878aSAndroid Build Coastguard Worker #define PW_ASSIGN_IF_READY(lhs, expr) \ 220*61c4878aSAndroid Build Coastguard Worker auto __priv = (expr); \ 221*61c4878aSAndroid Build Coastguard Worker if (!__priv.IsReady()) { \ 222*61c4878aSAndroid Build Coastguard Worker return pw::async::Pending; \ 223*61c4878aSAndroid Build Coastguard Worker } \ 224*61c4878aSAndroid Build Coastguard Worker lhs = std::move(__priv.Value()) \ 225*61c4878aSAndroid Build Coastguard Worker 226*61c4878aSAndroid Build Coastguard Worker MaybeReady<Bar> PollCreateBar(Context& cx); 227*61c4878aSAndroid Build Coastguard Worker 228*61c4878aSAndroid Build Coastguard Worker Poll<Foo> DoSomething(Context& cx) { 229*61c4878aSAndroid Build Coastguard Worker PW_ASSIGN_IF_READY(Bar b, PollCreateBar(cx)); 230*61c4878aSAndroid Build Coastguard Worker return CreateFoo(); 231*61c4878aSAndroid Build Coastguard Worker } 232*61c4878aSAndroid Build Coastguard Worker 233*61c4878aSAndroid Build Coastguard WorkerThis is similar to the role of the ``std::nullopt_t`` type. 234*61c4878aSAndroid Build Coastguard Worker 235*61c4878aSAndroid Build Coastguard WorkerThe ``Dispatcher`` Type 236*61c4878aSAndroid Build Coastguard Worker======================= 237*61c4878aSAndroid Build Coastguard WorkerDispatchers are the event loops responsible for running ``Task`` s. They sleep 238*61c4878aSAndroid Build Coastguard Workerwhen there is no work to do, and wake up when there are ``Task`` s ready to 239*61c4878aSAndroid Build Coastguard Workermake progress. 240*61c4878aSAndroid Build Coastguard Worker 241*61c4878aSAndroid Build Coastguard WorkerOn some platforms, the ``Dispatcher`` may also provide special hooks in order 242*61c4878aSAndroid Build Coastguard Workerto support single-threaded asynchronous I/O. 243*61c4878aSAndroid Build Coastguard Worker 244*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 245*61c4878aSAndroid Build Coastguard Worker 246*61c4878aSAndroid Build Coastguard Worker class Dispatcher { 247*61c4878aSAndroid Build Coastguard Worker public: 248*61c4878aSAndroid Build Coastguard Worker /// Tells the ``Dispatcher`` to run ``Task`` to completion. 249*61c4878aSAndroid Build Coastguard Worker /// This method does not block. 250*61c4878aSAndroid Build Coastguard Worker /// 251*61c4878aSAndroid Build Coastguard Worker /// After ``Post`` is called, ``Task::Poll`` will be invoked once. 252*61c4878aSAndroid Build Coastguard Worker /// If ``Task::Poll`` does not complete, the ``Dispatcher`` will wait 253*61c4878aSAndroid Build Coastguard Worker /// until the ``Task`` is "awoken", at which point it will call ``Poll`` 254*61c4878aSAndroid Build Coastguard Worker /// again until the ``Task`` completes. 255*61c4878aSAndroid Build Coastguard Worker void Post(Task&); 256*61c4878aSAndroid Build Coastguard Worker ... 257*61c4878aSAndroid Build Coastguard Worker }; 258*61c4878aSAndroid Build Coastguard Worker 259*61c4878aSAndroid Build Coastguard WorkerThe ``Waker`` Type 260*61c4878aSAndroid Build Coastguard Worker================== 261*61c4878aSAndroid Build Coastguard WorkerA ``Waker`` is responsible for telling a ``Dispatcher`` when a ``Task`` is 262*61c4878aSAndroid Build Coastguard Workerready to be ``Poll`` ed again. This allows ``Dispatcher`` s to intelligently 263*61c4878aSAndroid Build Coastguard Workerschedule calls to ``Poll`` rather than retrying in a loop (this is the 264*61c4878aSAndroid Build Coastguard Worker"informed" part of "informed Poll"). 265*61c4878aSAndroid Build Coastguard Worker 266*61c4878aSAndroid Build Coastguard WorkerWhen a ``Dispatcher`` calls ``Task::Poll``, it provides a ``Waker`` that will 267*61c4878aSAndroid Build Coastguard Workerenqueue the ``Task`` when awoken. ``Dispatcher`` s can implement this 268*61c4878aSAndroid Build Coastguard Workerfunctionality by having ``Waker`` add the ``Task`` to an intrusive linked list, 269*61c4878aSAndroid Build Coastguard Workeradd a pointer to the ``Task`` to a ``Dispatcher``-managed vector, or by pushing 270*61c4878aSAndroid Build Coastguard Workera ``Task`` ID onto a system-level async construct such as ``epoll``. 271*61c4878aSAndroid Build Coastguard Worker 272*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 273*61c4878aSAndroid Build Coastguard Worker 274*61c4878aSAndroid Build Coastguard Worker /// An object which can respond to asynchronous events by queueing work to 275*61c4878aSAndroid Build Coastguard Worker /// be done in response, such as placing a ``Task`` on a ``Dispatcher`` loop. 276*61c4878aSAndroid Build Coastguard Worker class Waker { 277*61c4878aSAndroid Build Coastguard Worker public: 278*61c4878aSAndroid Build Coastguard Worker /// Wakes up the ``Waker``'s creator, alerting it that an asynchronous 279*61c4878aSAndroid Build Coastguard Worker /// event has occurred that may allow it to make progress. 280*61c4878aSAndroid Build Coastguard Worker /// 281*61c4878aSAndroid Build Coastguard Worker /// ``Wake`` operates on an rvalue reference (``&&``) in order to indicate 282*61c4878aSAndroid Build Coastguard Worker /// that the event that was waited on has been completed. This makes it 283*61c4878aSAndroid Build Coastguard Worker /// possible to track the outstanding events that may cause a ``Task`` to 284*61c4878aSAndroid Build Coastguard Worker /// wake up and make progress. 285*61c4878aSAndroid Build Coastguard Worker void Wake() &&; 286*61c4878aSAndroid Build Coastguard Worker 287*61c4878aSAndroid Build Coastguard Worker /// Creates a second ``Waker`` from this ``Waker``. 288*61c4878aSAndroid Build Coastguard Worker /// 289*61c4878aSAndroid Build Coastguard Worker /// ``Clone`` is made explicit in order to allow for easier tracking of 290*61c4878aSAndroid Build Coastguard Worker /// the different ``Waker``s that may wake up a ``Task``. 291*61c4878aSAndroid Build Coastguard Worker Waker Clone(Token wait_reason_indicator) &; 292*61c4878aSAndroid Build Coastguard Worker ... 293*61c4878aSAndroid Build Coastguard Worker }; 294*61c4878aSAndroid Build Coastguard Worker 295*61c4878aSAndroid Build Coastguard WorkerThe ``Wake`` function itself may be called by any system with knowledge that 296*61c4878aSAndroid Build Coastguard Workerthe ``Task`` is now ready to make progress. This can be done from an interrupt, 297*61c4878aSAndroid Build Coastguard Workerfrom a separate task, from another thread, or from any other function that 298*61c4878aSAndroid Build Coastguard Workerknows that the `Poll`'d type may be able to make progress. 299*61c4878aSAndroid Build Coastguard Worker 300*61c4878aSAndroid Build Coastguard WorkerThe ``Context`` Type 301*61c4878aSAndroid Build Coastguard Worker==================== 302*61c4878aSAndroid Build Coastguard Worker``Context`` is a bundle of arguments supplied to ``Task::Poll`` that give the 303*61c4878aSAndroid Build Coastguard Worker``Task`` information about its asynchronous environment. The most important 304*61c4878aSAndroid Build Coastguard Workerparts of the ``Context`` are the ``Dispatcher``, which is used to ``Post`` 305*61c4878aSAndroid Build Coastguard Workernew ``Task`` s, and the ``Waker``, which is used to tell the ``Dispatcher`` 306*61c4878aSAndroid Build Coastguard Workerwhen to run this ``Task`` again. 307*61c4878aSAndroid Build Coastguard Worker 308*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 309*61c4878aSAndroid Build Coastguard Worker 310*61c4878aSAndroid Build Coastguard Worker class Context { 311*61c4878aSAndroid Build Coastguard Worker public: 312*61c4878aSAndroid Build Coastguard Worker Context(Dispatcher&, Waker&); 313*61c4878aSAndroid Build Coastguard Worker Dispatcher& Dispatcher(); 314*61c4878aSAndroid Build Coastguard Worker Waker& Waker(); 315*61c4878aSAndroid Build Coastguard Worker ... 316*61c4878aSAndroid Build Coastguard Worker }; 317*61c4878aSAndroid Build Coastguard Worker 318*61c4878aSAndroid Build Coastguard WorkerThe ``Task`` Type 319*61c4878aSAndroid Build Coastguard Worker================= 320*61c4878aSAndroid Build Coastguard WorkerFinally, the ``Task`` type is implemented by users in order to run some 321*61c4878aSAndroid Build Coastguard Workerasynchronous work. When a new asynchronous "thread" of execution must be run, 322*61c4878aSAndroid Build Coastguard Workerusers can create a new ``Task`` object and send it to be run on a 323*61c4878aSAndroid Build Coastguard Worker``Dispatcher``. 324*61c4878aSAndroid Build Coastguard Worker 325*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 326*61c4878aSAndroid Build Coastguard Worker 327*61c4878aSAndroid Build Coastguard Worker /// A task which may complete one or more asynchronous operations. 328*61c4878aSAndroid Build Coastguard Worker /// 329*61c4878aSAndroid Build Coastguard Worker /// ``Task`` s should be actively ``Poll`` ed to completion, either by a 330*61c4878aSAndroid Build Coastguard Worker /// ``Dispatcher`` or by a parent ``Task`` object. 331*61c4878aSAndroid Build Coastguard Worker class Task { 332*61c4878aSAndroid Build Coastguard Worker public: 333*61c4878aSAndroid Build Coastguard Worker MaybeReady<Complete> Poll(Context&); 334*61c4878aSAndroid Build Coastguard Worker ... 335*61c4878aSAndroid Build Coastguard Worker protected: 336*61c4878aSAndroid Build Coastguard Worker /// Returns whether or not the ``Task`` has completed. 337*61c4878aSAndroid Build Coastguard Worker /// 338*61c4878aSAndroid Build Coastguard Worker /// If the ``Task`` has not completed, `Poll::Pending` will be returned, 339*61c4878aSAndroid Build Coastguard Worker /// and `context.Waker()` will receive a `Wake()` call when the ``Task`` 340*61c4878aSAndroid Build Coastguard Worker /// is ready to make progress and should be ``Poll`` ed again. 341*61c4878aSAndroid Build Coastguard Worker virtual MaybeReady<Complete> DoPoll(Context&) = 0; 342*61c4878aSAndroid Build Coastguard Worker ... 343*61c4878aSAndroid Build Coastguard Worker }; 344*61c4878aSAndroid Build Coastguard Worker 345*61c4878aSAndroid Build Coastguard WorkerThis structure makes it possible to run complex asynchronous ``Task`` s 346*61c4878aSAndroid Build Coastguard Workercontaining multiple concurrent or sequential asynchronous events. 347*61c4878aSAndroid Build Coastguard Worker 348*61c4878aSAndroid Build Coastguard Worker------------------------------------ 349*61c4878aSAndroid Build Coastguard WorkerRelationship to Futures and Promises 350*61c4878aSAndroid Build Coastguard Worker------------------------------------ 351*61c4878aSAndroid Build Coastguard WorkerThe terms "future" and "promise" are unfortunately quite overloaded. This SEED 352*61c4878aSAndroid Build Coastguard Workerdoes not propose a "method chaining" API (e.g. ``.AndThen([](..) { ... }``), nor 353*61c4878aSAndroid Build Coastguard Workeris creating reference-counted, blocking handles to the output of other threads 354*61c4878aSAndroid Build Coastguard Workera la ``std::future``. 355*61c4878aSAndroid Build Coastguard Worker 356*61c4878aSAndroid Build Coastguard WorkerWhere this SEED refers to ``Future`` types (e.g. ``SendFuture`` in the summary 357*61c4878aSAndroid Build Coastguard Workerexample), it means only a type which offers a ``Poll(Context&)`` method and 358*61c4878aSAndroid Build Coastguard Workerreturn some ``MaybeReady<T>`` value. This common pattern can be used to build 359*61c4878aSAndroid Build Coastguard Workervarious asynchronous state machines which optionally return a value upon 360*61c4878aSAndroid Build Coastguard Workercompletion. 361*61c4878aSAndroid Build Coastguard Worker 362*61c4878aSAndroid Build Coastguard Worker--------------------------------------------- 363*61c4878aSAndroid Build Coastguard WorkerUsage In The Rust Ecosystem Shows Feasability 364*61c4878aSAndroid Build Coastguard Worker--------------------------------------------- 365*61c4878aSAndroid Build Coastguard WorkerThe ``Poll``-based ``Task`` approach suggested here is similar to the one 366*61c4878aSAndroid Build Coastguard Workeradopted by Rust's 367*61c4878aSAndroid Build Coastguard Worker`Future type <https://doc.rust-lang.org/stable/std/future/trait.Future.html>`_. 368*61c4878aSAndroid Build Coastguard WorkerThe ``Task`` class in this SEED is analogous to Rust's ``Future<Output = ()>`` 369*61c4878aSAndroid Build Coastguard Workertype. This model has proven usable on small environments without dynamic allocation. 370*61c4878aSAndroid Build Coastguard Worker 371*61c4878aSAndroid Build Coastguard WorkerDue to compiler limitations, Rust's ``async fn`` language feature will often 372*61c4878aSAndroid Build Coastguard Workergenerate ``Future`` s which suffer from code size issues. However, 373*61c4878aSAndroid Build Coastguard Workermanual implementations of Rust's ``Future`` trait (not using ``async fn``) do 374*61c4878aSAndroid Build Coastguard Workernot have this issue. 375*61c4878aSAndroid Build Coastguard Worker 376*61c4878aSAndroid Build Coastguard WorkerWe believe the success of Rust's ``Poll``-based ``Future`` type demonstrates 377*61c4878aSAndroid Build Coastguard Workerthat the approach taken in this SEED can meet the needs of Pigweed users. 378*61c4878aSAndroid Build Coastguard Worker 379*61c4878aSAndroid Build Coastguard Worker--------- 380*61c4878aSAndroid Build Coastguard WorkerCode Size 381*61c4878aSAndroid Build Coastguard Worker--------- 382*61c4878aSAndroid Build Coastguard Worker`Some experiments have been done 383*61c4878aSAndroid Build Coastguard Worker<https://pigweed-review.googlesource.com/c/pigweed/experimental/+/154570>`_ 384*61c4878aSAndroid Build Coastguard Workerto compare the size of the code generated by 385*61c4878aSAndroid Build Coastguard Workera ``Poll``-based approach with code generated with the existing ``pw::async`` 386*61c4878aSAndroid Build Coastguard WorkerAPIs. These experiments have so far found that the ``Poll``-based approach 387*61c4878aSAndroid Build Coastguard Workercreates binaries with smaller code size due to an increased opportunity for 388*61c4878aSAndroid Build Coastguard Workerinlining, static dispatch, and a smaller number of separate ``Task`` objects. 389*61c4878aSAndroid Build Coastguard Worker 390*61c4878aSAndroid Build Coastguard WorkerThe experimental ``pw_async_bench`` examples show that the ``Poll``-based 391*61c4878aSAndroid Build Coastguard Workerapproach offers more than 2kB of savings on a small ``Socket``-like example. 392*61c4878aSAndroid Build Coastguard Worker 393*61c4878aSAndroid Build Coastguard Worker------------------------ 394*61c4878aSAndroid Build Coastguard WorkerThe ``pw::async`` Facade 395*61c4878aSAndroid Build Coastguard Worker------------------------ 396*61c4878aSAndroid Build Coastguard WorkerThis SEED proposes changing ``Dispatcher`` from a virtual base into a 397*61c4878aSAndroid Build Coastguard Workerplatform-specific concrete type. 398*61c4878aSAndroid Build Coastguard Worker 399*61c4878aSAndroid Build Coastguard WorkerThe existing ``pw::async::Dispatcher`` class is ``virtual`` in order to support 400*61c4878aSAndroid Build Coastguard Workeruse of an alternative ``Dispatcher`` implementation in tests. However, this 401*61c4878aSAndroid Build Coastguard Workerapproach assumes that ``Task`` s are capable of running on arbitrary 402*61c4878aSAndroid Build Coastguard Workerimplementations of the ``Dispatcher`` virtual interface. In practice, this is 403*61c4878aSAndroid Build Coastguard Workernot the case. 404*61c4878aSAndroid Build Coastguard Worker 405*61c4878aSAndroid Build Coastguard WorkerDifferent platforms will use different native ``Dispatcher`` waiting primitives 406*61c4878aSAndroid Build Coastguard Workerincluding ``epoll``, ``kqueue``, IOCP, Fuchsia's ``libasync``/``zx_port``, and 407*61c4878aSAndroid Build Coastguard Workerlower-level waiting primitives such as Zephyr's RTIO queue. 408*61c4878aSAndroid Build Coastguard Worker 409*61c4878aSAndroid Build Coastguard WorkerEach of these primitives is strongly coupled with native async events, such as 410*61c4878aSAndroid Build Coastguard WorkerIO or buffer readiness. In order to support ``Dispatcher``-native IO events, 411*61c4878aSAndroid Build Coastguard WorkerIO objects must be able to guarantee that they are running on a compatible 412*61c4878aSAndroid Build Coastguard Worker``Dispatcher``. In Pigweed, this can be accomplished through the use of the 413*61c4878aSAndroid Build Coastguard Workerfacade pattern. 414*61c4878aSAndroid Build Coastguard Worker 415*61c4878aSAndroid Build Coastguard WorkerThe facade patterns allows for concrete, platform-dependent definitions of the 416*61c4878aSAndroid Build Coastguard Worker``Task``, ``Context``, ``Waker``, and ``Dispatcher`` types. This allows these 417*61c4878aSAndroid Build Coastguard Workerobjects to interact with one another as necessary to implement fast scheduling 418*61c4878aSAndroid Build Coastguard Workerwith minimal in-memory or code size overhead. 419*61c4878aSAndroid Build Coastguard Worker 420*61c4878aSAndroid Build Coastguard WorkerThis approach enables storing platform-specific per- ``Task`` scheduling details 421*61c4878aSAndroid Build Coastguard Workerinline with the ``Task`` itself, enabling zero-allocation ``Task`` scheduling 422*61c4878aSAndroid Build Coastguard Workerwithout the need for additional resource pools. 423*61c4878aSAndroid Build Coastguard Worker 424*61c4878aSAndroid Build Coastguard WorkerThis also allows for native integration with platform-specific I/O primitives 425*61c4878aSAndroid Build Coastguard Workerincluding ``epoll``, ``kqueue``, IOCP, and others, but also lower-level 426*61c4878aSAndroid Build Coastguard Workerwaiting primitives such as Zephyr's RTIO queue. 427*61c4878aSAndroid Build Coastguard Worker 428*61c4878aSAndroid Build Coastguard WorkerTesting 429*61c4878aSAndroid Build Coastguard Worker======= 430*61c4878aSAndroid Build Coastguard WorkerMoving ``Dispatcher`` to a non-virtual facade means that the previous approach 431*61c4878aSAndroid Build Coastguard Workerof testing with a ``FakeDispatcher`` would require a separate toolchain in 432*61c4878aSAndroid Build Coastguard Workerorder to provide a different instantiation of the ``Dispatcher`` type. However, 433*61c4878aSAndroid Build Coastguard Workerwe can adopt a simpler approach: the ``Dispatcher`` type can offer minimial 434*61c4878aSAndroid Build Coastguard Workertesting primitives natively: 435*61c4878aSAndroid Build Coastguard Worker 436*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 437*61c4878aSAndroid Build Coastguard Worker 438*61c4878aSAndroid Build Coastguard Worker class Dispatcher { 439*61c4878aSAndroid Build Coastguard Worker public: 440*61c4878aSAndroid Build Coastguard Worker ... 441*61c4878aSAndroid Build Coastguard Worker 442*61c4878aSAndroid Build Coastguard Worker /// Runs tasks until none are able to make immediate progress. 443*61c4878aSAndroid Build Coastguard Worker /// 444*61c4878aSAndroid Build Coastguard Worker /// Returns whether a ``Task`` was run. 445*61c4878aSAndroid Build Coastguard Worker bool RunUntilStalled(); 446*61c4878aSAndroid Build Coastguard Worker 447*61c4878aSAndroid Build Coastguard Worker /// Enable mock time, initializing the mock timer to some "zero"-like 448*61c4878aSAndroid Build Coastguard Worker /// value. 449*61c4878aSAndroid Build Coastguard Worker void InitializeMockTime(); 450*61c4878aSAndroid Build Coastguard Worker 451*61c4878aSAndroid Build Coastguard Worker /// Advances the mock timer forwards by ``duration``. 452*61c4878aSAndroid Build Coastguard Worker void AdvanceMockTime(chrono::SystemClock::duration duration); 453*61c4878aSAndroid Build Coastguard Worker }; 454*61c4878aSAndroid Build Coastguard Worker 455*61c4878aSAndroid Build Coastguard WorkerThese primitives are sufficient for testing with mock time. They allow 456*61c4878aSAndroid Build Coastguard Workertest authors to avoid deadlocks, timeouts, or race conditions. 457*61c4878aSAndroid Build Coastguard Worker 458*61c4878aSAndroid Build Coastguard WorkerDownsides of Built-in Testing Functions 459*61c4878aSAndroid Build Coastguard Worker--------------------------------------- 460*61c4878aSAndroid Build Coastguard WorkerRequiring concrete ``Dispatcher`` types to include the testing functions above 461*61c4878aSAndroid Build Coastguard Workermeans that the production ``Dispatcher`` implementations will have code in them 462*61c4878aSAndroid Build Coastguard Workerthat is only needed for testing. 463*61c4878aSAndroid Build Coastguard Worker 464*61c4878aSAndroid Build Coastguard WorkerHowever, these additions are minimal: mocking time introduces a single branch 465*61c4878aSAndroid Build Coastguard Workerfor each timer access, which is still likely to be more efficient than the 466*61c4878aSAndroid Build Coastguard Workervirtual function call that was required under the previous model. 467*61c4878aSAndroid Build Coastguard Worker 468*61c4878aSAndroid Build Coastguard WorkerAdvantages of Built-in Testing Functions 469*61c4878aSAndroid Build Coastguard Worker---------------------------------------- 470*61c4878aSAndroid Build Coastguard WorkerTesting with a "real" ``Dispatcher`` implementation ensures that: 471*61c4878aSAndroid Build Coastguard Worker 472*61c4878aSAndroid Build Coastguard Worker* All ``pw::async`` platforms provide support for testing 473*61c4878aSAndroid Build Coastguard Worker* The ``Dispatcher`` used for testing will support the same I/O operations and 474*61c4878aSAndroid Build Coastguard Worker features provided by the production ``Dispatcher`` 475*61c4878aSAndroid Build Coastguard Worker* Tests will run under conditions as-close-to-production as possible. This will 476*61c4878aSAndroid Build Coastguard Worker allow catching bugs that are caused by the interaction of the code and the 477*61c4878aSAndroid Build Coastguard Worker particular ``Dispatcher`` on which it runs. 478*61c4878aSAndroid Build Coastguard Worker 479*61c4878aSAndroid Build Coastguard WorkerEnabling Dynamic ``Task`` Lifetimes 480*61c4878aSAndroid Build Coastguard Worker=================================== 481*61c4878aSAndroid Build Coastguard WorkerWhile some ``Task`` s may be static, others may not be. For these, we need a 482*61c4878aSAndroid Build Coastguard Workermechanism to ensure that: 483*61c4878aSAndroid Build Coastguard Worker 484*61c4878aSAndroid Build Coastguard Worker* ``Task`` resources are not destroyed while ``Waker`` s that may post them 485*61c4878aSAndroid Build Coastguard Worker to a ``Dispatcher`` remain. 486*61c4878aSAndroid Build Coastguard Worker* ``Task`` resources are not destroyed while the ``Task`` itself is running 487*61c4878aSAndroid Build Coastguard Worker or is queued to run. 488*61c4878aSAndroid Build Coastguard Worker 489*61c4878aSAndroid Build Coastguard WorkerIn order to enable this, platforms should clear all ``Waker`` s referencing a 490*61c4878aSAndroid Build Coastguard Worker``Task`` when the ``Task`` completes: that ``Task`` will make no further 491*61c4878aSAndroid Build Coastguard Workerprogress, so ``Wake`` ing it serves no purpose. 492*61c4878aSAndroid Build Coastguard Worker 493*61c4878aSAndroid Build Coastguard WorkerOnce all ``Waker`` s have been cleared and the ``Task`` has finished running 494*61c4878aSAndroid Build Coastguard Workeron the ``Dispatcher``, the ``Dispatcher`` should call that ``Task`` s 495*61c4878aSAndroid Build Coastguard Worker``Cleanup`` function so that the ``Task`` can free any associated dynamic 496*61c4878aSAndroid Build Coastguard Workerresources. During this ``Cleanup`` function, no other resources of ``Task`` 497*61c4878aSAndroid Build Coastguard Workermay be accessed by the application author until the ``Task`` has been 498*61c4878aSAndroid Build Coastguard Workerre-initialized. If the memory associated with the ``Task`` is to be reused, 499*61c4878aSAndroid Build Coastguard Workerthe ``Task`` object itself must be reinitialized by invoking the ``Init`` 500*61c4878aSAndroid Build Coastguard Workerfunction. 501*61c4878aSAndroid Build Coastguard Worker 502*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 503*61c4878aSAndroid Build Coastguard Worker 504*61c4878aSAndroid Build Coastguard Worker class Task { 505*61c4878aSAndroid Build Coastguard Worker public: 506*61c4878aSAndroid Build Coastguard Worker ... 507*61c4878aSAndroid Build Coastguard Worker void Init(); 508*61c4878aSAndroid Build Coastguard Worker virtual void Cleanup(); 509*61c4878aSAndroid Build Coastguard Worker ... 510*61c4878aSAndroid Build Coastguard Worker }; 511*61c4878aSAndroid Build Coastguard Worker 512*61c4878aSAndroid Build Coastguard WorkerThis allows downstream ``Task`` inheritors to implement dynamic free-ing of 513*61c4878aSAndroid Build Coastguard Worker``Task`` resources, while also allowing the ``Dispatcher`` implementation the 514*61c4878aSAndroid Build Coastguard Workeropportunity to clean up its own resources stored inside of the ``Task`` base 515*61c4878aSAndroid Build Coastguard Workerclass. 516*61c4878aSAndroid Build Coastguard Worker 517*61c4878aSAndroid Build Coastguard WorkerWaker 518*61c4878aSAndroid Build Coastguard Worker===== 519*61c4878aSAndroid Build Coastguard Worker``Waker`` s will at first only be created via the ``Dispatcher`` 520*61c4878aSAndroid Build Coastguard Workerimplementation, via cloning, or by the null constructor. Later on, the API may 521*61c4878aSAndroid Build Coastguard Workerbe expanded to allow for waking sub-tasks. The necessity of this at Pigweed's 522*61c4878aSAndroid Build Coastguard Workerscale has not yet been determined. 523*61c4878aSAndroid Build Coastguard Worker 524*61c4878aSAndroid Build Coastguard WorkerTimer 525*61c4878aSAndroid Build Coastguard Worker===== 526*61c4878aSAndroid Build Coastguard Worker``pw::async`` will additionally provide a ``Timer`` type. A ``Timer`` can be 527*61c4878aSAndroid Build Coastguard Worker``Poll``'d by a ``Task`` in order to determine if a certain amount of time has 528*61c4878aSAndroid Build Coastguard Workerpassed. This can be used to implement timeouts or to schedule work. 529*61c4878aSAndroid Build Coastguard Worker 530*61c4878aSAndroid Build Coastguard WorkerOne possible ``Timer`` API would be as follows: 531*61c4878aSAndroid Build Coastguard Worker 532*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 533*61c4878aSAndroid Build Coastguard Worker 534*61c4878aSAndroid Build Coastguard Worker class Timer { 535*61c4878aSAndroid Build Coastguard Worker public: 536*61c4878aSAndroid Build Coastguard Worker Timer(Context&, chrono::SystemClock::time_point deadline); 537*61c4878aSAndroid Build Coastguard Worker Timer(Context&, chrono::SystemClock::duration delay); 538*61c4878aSAndroid Build Coastguard Worker pw::MaybeReady<Complete> Poll(Context&); 539*61c4878aSAndroid Build Coastguard Worker ... 540*61c4878aSAndroid Build Coastguard Worker }; 541*61c4878aSAndroid Build Coastguard Worker 542*61c4878aSAndroid Build Coastguard WorkerIn order to enable this, the ``Dispatcher`` base class will include the 543*61c4878aSAndroid Build Coastguard Workerfollowing functions which implementations should use to trigger timers: 544*61c4878aSAndroid Build Coastguard Worker 545*61c4878aSAndroid Build Coastguard Worker.. code-block:: cpp 546*61c4878aSAndroid Build Coastguard Worker 547*61c4878aSAndroid Build Coastguard Worker class DispatcherBase { 548*61c4878aSAndroid Build Coastguard Worker public: 549*61c4878aSAndroid Build Coastguard Worker ... 550*61c4878aSAndroid Build Coastguard Worker protected: 551*61c4878aSAndroid Build Coastguard Worker /// Returns the time of the earliest timer currently scheduled to fire. 552*61c4878aSAndroid Build Coastguard Worker std::optional<chrono::SystemClock::time_point> EarliestTimerExpiry(); 553*61c4878aSAndroid Build Coastguard Worker 554*61c4878aSAndroid Build Coastguard Worker /// Marks all ``Timer`` s with a time before ``time_point`` as complete, 555*61c4878aSAndroid Build Coastguard Worker /// and awakens any associated tasks. 556*61c4878aSAndroid Build Coastguard Worker /// 557*61c4878aSAndroid Build Coastguard Worker /// Returns whether any ``Timer`` objects were marked complete. 558*61c4878aSAndroid Build Coastguard Worker bool AwakenTimersUpTo(chrono::SystemClock::time_point); 559*61c4878aSAndroid Build Coastguard Worker 560*61c4878aSAndroid Build Coastguard Worker /// Invoked when a new earliest ``Timer`` is created. 561*61c4878aSAndroid Build Coastguard Worker /// 562*61c4878aSAndroid Build Coastguard Worker /// ``Dispatcher`` implementations can override this to receive 563*61c4878aSAndroid Build Coastguard Worker /// notifications when a new timer is added. 564*61c4878aSAndroid Build Coastguard Worker virtual void NewEarliestTimer(); 565*61c4878aSAndroid Build Coastguard Worker ... 566*61c4878aSAndroid Build Coastguard Worker }; 567*61c4878aSAndroid Build Coastguard Worker 568*61c4878aSAndroid Build Coastguard Worker--------------------- 569*61c4878aSAndroid Build Coastguard WorkerC++ Coroutine Support 570*61c4878aSAndroid Build Coastguard Worker--------------------- 571*61c4878aSAndroid Build Coastguard WorkerThe informed ``Poll`` approach is well-suited to 572*61c4878aSAndroid Build Coastguard Worker`C++20's coroutines <https://en.cppreference.com/w/cpp/language/coroutines>`_. 573*61c4878aSAndroid Build Coastguard WorkerCoroutines using the ``co_await`` and ``co_return`` expressions can 574*61c4878aSAndroid Build Coastguard Workerautomatically create and wait on ``Task`` types, whose base class will 575*61c4878aSAndroid Build Coastguard Workerimplement the ``std::coroutine_traits`` interface on C++20 and later. 576*61c4878aSAndroid Build Coastguard Worker 577*61c4878aSAndroid Build Coastguard WorkerDynamic Allocation 578*61c4878aSAndroid Build Coastguard Worker================== 579*61c4878aSAndroid Build Coastguard WorkerNote that C++ coroutines allocate their state dynamically using 580*61c4878aSAndroid Build Coastguard Worker``operator new``, and therefore are not usable on systems in which dynamic 581*61c4878aSAndroid Build Coastguard Workerallocation is not available or where recovery from allocation failure is 582*61c4878aSAndroid Build Coastguard Workerrequired. 583*61c4878aSAndroid Build Coastguard Worker 584*61c4878aSAndroid Build Coastguard Worker------------ 585*61c4878aSAndroid Build Coastguard WorkerRust Interop 586*61c4878aSAndroid Build Coastguard Worker------------ 587*61c4878aSAndroid Build Coastguard WorkerRust uses a similar informed ``Poll`` model for its ``Future`` trait. This 588*61c4878aSAndroid Build Coastguard Workerallows ``pw::async`` code to invoke Rust-based ``Future`` s by creating a 589*61c4878aSAndroid Build Coastguard WorkerRust ``Waker`` which invokes the C++ ``Waker``, and performing cross-language 590*61c4878aSAndroid Build Coastguard Worker``Poll`` ing. 591*61c4878aSAndroid Build Coastguard Worker 592*61c4878aSAndroid Build Coastguard WorkerRust support is not currently planned for the initial version of ``pw::async``, 593*61c4878aSAndroid Build Coastguard Workerbut will likely come in the future as Pigweed support for Rust expands. 594*61c4878aSAndroid Build Coastguard Worker 595*61c4878aSAndroid Build Coastguard Worker------------------------------------------------ 596*61c4878aSAndroid Build Coastguard WorkerSupport for Traditional Callback-Style Codebases 597*61c4878aSAndroid Build Coastguard Worker------------------------------------------------ 598*61c4878aSAndroid Build Coastguard WorkerOne concern is interop with codebases which adopt a more traditional 599*61c4878aSAndroid Build Coastguard Workercallback-driven design, such as the one currently supported by ``pw::async``. 600*61c4878aSAndroid Build Coastguard WorkerThese models will continue to be supported under the new design, and can be 601*61c4878aSAndroid Build Coastguard Workermodeled as a ``Task`` which runs a single function when ``Poll`` ed. 602*61c4878aSAndroid Build Coastguard Worker 603*61c4878aSAndroid Build Coastguard Worker--------- 604*61c4878aSAndroid Build Coastguard WorkerMigration 605*61c4878aSAndroid Build Coastguard Worker--------- 606*61c4878aSAndroid Build Coastguard WorkerFor ease of implementation and in order to ensure a smooth transition, this API 607*61c4878aSAndroid Build Coastguard Workerwill initially live alongside the current ``pw::async`` interface. This API 608*61c4878aSAndroid Build Coastguard Workerwill first be tested with one or more trial usages in order to stabilize the 609*61c4878aSAndroid Build Coastguard Workerinterface and ensure its suitability for Pigweed users. 610*61c4878aSAndroid Build Coastguard Worker 611*61c4878aSAndroid Build Coastguard WorkerFollowing that, the previous ``pw::async`` implementation will be deprecated. 612*61c4878aSAndroid Build Coastguard WorkerA shim will be provided to allow users of the previous API to easily migrate 613*61c4878aSAndroid Build Coastguard Workertheir code onto the new ``pw::async`` implementation. After migrating to the 614*61c4878aSAndroid Build Coastguard Workernew implementation, users can gradually transition to the new ``Poll``-based 615*61c4878aSAndroid Build Coastguard WorkerAPIs as-desired. It will be possible to intermix legacy-style and 616*61c4878aSAndroid Build Coastguard Worker``Poll``-based async code within the same dispatcher loop, allowing legacy 617*61c4878aSAndroid Build Coastguard Workercodebases to adopt the ``Poll``-based model for new subsystems. 618