xref: /aosp_15_r20/external/pigweed/seed/0112.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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