1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef LIB_FIT_PROMISE_H_
6 #define LIB_FIT_PROMISE_H_
7
8 #include <assert.h>
9
10 #include <tuple>
11 #include <type_traits>
12 #include <utility>
13
14 #include "function.h"
15 #include "promise_internal.h"
16 #include "result.h"
17 #include "variant.h"
18
19 namespace fit {
20
21 // A |fit::promise| is a building block for asynchronous control flow that
22 // wraps an asynchronous task in the form of a "continuation" that is
23 // repeatedly invoked by an executor until it produces a result.
24 //
25 // Additional asynchronous tasks can be chained onto the promise using
26 // a variety of combinators such as |then()|.
27 //
28 // Use |fit::make_promise()| to create a promise.
29 // Use |fit::future| to more conveniently hold a promise or its result.
30 // Use |fit::pending_task| to wrap a promise as a pending task for execution.
31 // Use |fit::executor| to execute a pending task.
32 // See examples below.
33 //
34 // Always look to the future; never look back.
35 //
36 // SYNOPSIS
37 //
38 // |V| is the type of value produced when the completes successfully.
39 // Defaults to |void|.
40 //
41 // |E| is the type of error produced when the completes with an error.
42 // Defaults to |void|.
43 //
44 // Class members are documented in |fit::promise_impl|.
45 //
46 // CHAINING PROMISES USING COMBINATORS
47 //
48 // Promises can be chained together using combinators such as |then()|
49 // which consume the original promise(s) and return a new combined promise.
50 //
51 // For example, the |then()| combinator returns a promise that has the effect
52 // of asynchronously awaiting completion of the prior promise (the instance
53 // upon which |then()| was called) then delivering its result to a handler
54 // function.
55 //
56 // Available combinators defined in this library:
57 //
58 // |then()|: run a handler when prior promise completes
59 // |and_then()|: run a handler when prior promise completes successfully
60 // |or_else()|: run a handler when prior promise completes with an error
61 // |inspect()|: examine result of prior promise
62 // |discard_result()|: discard result and unconditionally return
63 // fit::result<> when prior promise completes
64 // |wrap_with()|: applies a wrapper to the promise
65 // |box()|: wraps the promise's continuation into a |fit::function|
66 // |fit::join_promises()|: await multiple promises, once they all complete
67 // return a tuple of their results
68 //
69 // You can also create your own custom combinators by crafting new
70 // types of continuations.
71 //
72 // CONTINUATIONS AND HANDLERS
73 //
74 // Internally, |fit::promise| wraps a continuation (a kind of callable
75 // object) that holds the state of the asynchronous task and provides a
76 // means for making progress through repeated invocation.
77 //
78 // A promise's continuation is generated through the use of factories
79 // such as |make_promise()| and combinators such as |then()|. Most of
80 // these functions accept a client-supplied "handler" (another kind
81 // of callable object, often a lambda expression) which performs the actual
82 // computations.
83 //
84 // Continuations have a very regular interface: they always accept a
85 // |fit::context&| argument and return a |fit::result|. Conversely, handlers
86 // have a very flexible interface: clients can provide them in many forms
87 // all of which are documented by the individual functions which consume them.
88 // It's pretty easy to use: the library takes care of wrapping client-supplied
89 // handlers of all supported forms into the continuations it uses internally.
90 //
91 // THEORY OF OPERATION
92 //
93 // On its own, a promise is "inert"; it only makes progress in response to
94 // actions taken by its owner. The state of the promise never changes
95 // spontaneously or concurrently.
96 //
97 // Typically, a promise is executed by wrapping it into a |fit::pending_task|
98 // and scheduling it for execution using |fit::executor::schedule_task()|.
99 // A promise's |operator(fit::context&)| can also be invoked directly by its owner
100 // from within the scope of another task (this is used to implement combinators
101 // and futures) though the principle is the same.
102 //
103 // |fit::executor| is an abstract class that encapsulates a strategy for
104 // executing tasks. The executor is responsible for invoking each tasks's
105 // continuation until the task returns a non-pending result, indicating that
106 // the task has been completed.
107 //
108 // The method of execution and scheduling of each continuation call is left
109 // to the discretion of each executor implementation. Typical executor
110 // implementations may dispatch tasks on an event-driven message loop or on
111 // a thread pool. Developers are responsible for selecting appropriate
112 // executor implementations for their programs.
113 //
114 // During each invocation, the executor passes the continuation an execution
115 // context object represented by a subclass of |fit::context|. The continuation
116 // attempts to make progress then returns a value of type |fit::result| to
117 // indicate whether it completed successfully (signaled by |fit::ok()|),
118 // failed with an error (signaled by |fit::error()|, or was unable to complete
119 // the task during that invocation (signaled by |fit::pending()|).
120 // For example, a continuation may be unable to complete the task if it must
121 // asynchronously await completion of an I/O or IPC operation before it
122 // can proceed any further.
123 //
124 // If the continuation was unable to complete the task during its invocation,
125 // it may to call |fit::context::suspend_task()| to acquire a
126 // |fit::suspended_task| object. The continuation then arranges for the
127 // task to be resumed asynchronously (with |fit::suspended_task::resume_task()|)
128 // once it becomes possible for the promise to make forward progress again.
129 // Finally, the continuation returns returns |fit::pending()| to indicate to
130 // the executor that it was unable to complete the task during that invocation.
131 //
132 // When the executor receives a pending result from a task's continuation,
133 // it moves the task into a table of suspended tasks. A suspended task
134 // is considered abandoned if has not been resume and all remaining
135 // |fit::suspended_task| handles representing it have been dropped.
136 // When a task is abandoned, the executor removes it from its table of
137 // suspended tasks and destroys the task because it is not possible for the task
138 // to be resumed or to make progress from that state.
139 //
140 // See also |fit::single_threaded_executor| for a simple executor implementation.
141 //
142 // BOXED AND UNBOXED PROMISES
143 //
144 // To make combination and execution as efficient as possible, the promises
145 // returned by |fit::make_promise| and by combinators are parameterized by
146 // complicated continuation types that are hard to describe, often consisting of
147 // nested templates and lambdas. These are referred to as "unboxed"
148 // promises. In contrast, "boxed" promises are parameterized by a
149 // a |fit::function| that hides (or "erases") the type of the continuation
150 // thereby yielding type that is easier to describe.
151 //
152 // You can recognize boxed and unboxed promises by their types.
153 // Here are two examples:
154 //
155 // - A boxed promise type: `fit::promise<void, void>` which is an alias for
156 // `fit::promise_impl<void, void, std::function<fit::result<void, void>>`.
157 // - An unboxed promise type: `fit::promise_impl<void, void,
158 // fit::internal::then_continuation<...something unintelligible...>>`
159 //
160 // Although boxed promises are easier to manipulate, they may cause the
161 // continuation to be allocated on the heap. Chaining boxed promises can
162 // result in multiple allocations being produced.
163 //
164 // Conversely, unboxed promises have full type information. Not only does
165 // this defer heap allocation but it also makes it easier for the C++
166 // compiler to fuse a chains of unboxed promises together into a single
167 // object that is easier to optimize.
168 //
169 // Unboxed promises can be boxed by assigning them to a boxed promise
170 // type (such as |fit::promise<>|) or using the |box()| combinator.
171 //
172 // As a rule of thumb, always defer boxing of promises until it is necessary
173 // to transport them using a simpler type.
174 //
175 // Do this: (chaining as a single expression performs at most one heap allocation)
176 //
177 // fit::promise<> f = fit::make_promise([] { ... });
178 // .then([](fit::result<> result) { ... });
179 // .and_then([] { ... });
180 //
181 // Or this: (still only performs at most one heap allocation)
182 //
183 // auto f = fit::make_promise([] { ... });
184 // auto g = f.then([](fit::result<> result) { ... });
185 // auto h = g.and_then([] { ... });
186 // fit::promise<> boxed_h = h;
187 //
188 // But don't do this: (incurs up to three heap allocations due to eager boxing)
189 //
190 // fit::promise<> f = fit::make_promise([] { ... });
191 // fit::promise<> g = f.then([](fit::result<> result) { ... });
192 // fit::promise<> h = g.and_then([] { ... });
193 //
194 // SINGLE OWNERSHIP MODEL
195 //
196 // Promises have single-ownership semantics. This means that there
197 // can only be at most one reference to the task represented by its
198 // continuation along with any state held by that continuation.
199 //
200 // When a combinator is applied to a promise, ownership of its continuation
201 // is transferred to the combined promise, leaving the original promise
202 // in an "empty" state without a continuation. Note that it is an error
203 // to attempt to invoke an empty promise (will assert at runtime).
204 //
205 // This model greatly simplifies reasoning about object lifetime.
206 // If a promise goes out of scope without completing its task, the task
207 // is considered "abandoned", causing all associated state to be destroyed.
208 //
209 // Note that a promise may capture references to other objects whose lifetime
210 // differs from that of the promise. It is the responsibility of the promise
211 // to ensure reachability of the objects whose reference it captures such
212 // as by using reference counted pointers, weak pointers, or other appropriate
213 // mechanisms to ensure memory safety.
214 //
215 // THREADING MODEL
216 //
217 // Promise objects are not thread-safe themselves. You cannot call their
218 // methods concurrently (or re-entrantly). However, promises can safely
219 // be moved to other threads and executed there (unless their continuation
220 // requires thread affinity for some reason but that's beyond the scope
221 // of this document).
222 //
223 // This property of being thread-independent, combined with the single
224 // ownership model, greatly simplifies the implementation of thread pool
225 // based executors.
226 //
227 // RESULT RETENTION AND FIT::FUTURES
228 //
229 // A promise's continuation can only be executed to completion once.
230 // After it completes, it cannot be run again.
231 //
232 // This method of execution is very efficient; the promise's result is returned
233 // directly to its invoker; it is not copied or retained within the promise
234 // object itself. It is entirely the caller's responsibility to decide how to
235 // consume or retain the result if need be.
236 //
237 // For example, the caller can move the promise into a |fit::future| to
238 // more conveniently hold either the promise or its result upon completion.
239 //
240 // CLARIFICATION OF NOMENCLATURE
241 //
242 // In this library, the words "promise" and "future" have the following
243 // definitions:
244 //
245 // - A *promise* holds the function that performs an asynchronous task.
246 // It is the means to produce a value.
247 // - A *future* holds the value produced by an asynchronous task or a
248 // promise to produce that value if the task has not yet completed.
249 // It is a proxy for a value that is to be computed.
250 //
251 // Be aware that other libraries may use these terms slightly differently.
252 //
253 // For more information about the theory of futures and promises, see
254 // https://en.wikipedia.org/wiki/Futures_and_promises.
255 //
256 // COMPARISON WITH STD::FUTURE
257 //
258 // |std::future| provides a mechanism for running asynchronous tasks
259 // and awaiting their results on other threads. Waiting can be performed
260 // either by blocking the waiting thread or by polling the future.
261 // The manner in which tasks are scheduled and executed is entirely
262 // controlled by the C++ standard library and offers limited control
263 // to developers.
264 //
265 // |fit::promise| and |fit::future| provide a mechanism for running asynchronous
266 // tasks, chaining additional tasks using combinators, and awaiting their
267 // results. An executor is responsible for suspending tasks awaiting
268 // results of other tasks and is at liberty to run other tasks on the
269 // same thread rather than blocking. In addition, developers can create custom
270 // executors to implement their own policies for running tasks.
271 //
272 // Decoupling awaiting from blocking makes |fit::promise| quite versatile.
273 // |fit::promise| can also interoperate with other task dispatching mechanisms
274 // (including |std::future|) using adapters such as |fit::bridge|.
275 //
276 // EXAMPLE
277 //
278 // - https://fuchsia.googlesource.com/zircon/+/master/system/utest/fit/examples/promise_example1.cpp
279 // - https://fuchsia.googlesource.com/zircon/+/master/system/utest/fit/examples/promise_example2.cpp
280 //
281 template <typename V = void, typename E = void>
282 using promise = promise_impl<function<result<V, E>(fit::context&)>>;
283
284 // Promise implementation details.
285 // See |fit::promise| documentation for more information.
286 template <typename Continuation>
287 class promise_impl final {
288 static_assert(
289 ::fit::internal::is_continuation<Continuation>::value,
290 "Continuation type is invalid. A continuation is a callable object "
291 "with this signature: fit::result<V, E>(fit::context&).");
292
293 using state_type = nullable<Continuation>;
294
295 public:
296 // The type of callable object held by the promise.
297 // Its signature is: result_type(fit::context&).
298 using continuation_type = Continuation;
299
300 // The promise's result type.
301 // Equivalent to fit::result<value_type, error_type>.
302 using result_type = typename ::fit::internal::continuation_traits<
303 Continuation>::result_type;
304
305 // The type of value produced when the promise completes successfully.
306 // May be void.
307 using value_type = typename result_type::value_type;
308
309 // The type of value produced when the promise completes with an error.
310 // May be void.
311 using error_type = typename result_type::error_type;
312
313 // Creates an empty promise without a continuation.
314 // A continuation must be assigned before the promise can be used.
315 promise_impl() = default;
promise_impl(decltype (nullptr))316 explicit promise_impl(decltype(nullptr)) {}
317
318 // Creates a promise with a continuation.
319 // If |continuation| equals nullptr then the promise is empty.
promise_impl(continuation_type continuation)320 explicit promise_impl(continuation_type continuation)
321 : state_(std::move(continuation)) {}
322
323 // Converts from a promise holding a continuation that is assignable to
324 // to this promise's continuation type.
325 //
326 // This is typically used to create a promise with a boxed continuation
327 // type (such as |fit::function|) from an unboxed promise produced by
328 // |fit::make_promise| or by combinators.
329 //
330 // EXAMPLE
331 //
332 // // f is a promise_impl with a complicated unboxed type
333 // auto f = fit::make_promise([] { ... });
334 //
335 // // g wraps f's continuation
336 // fit::promise<> g = std::move(f);
337 //
338 template <typename OtherContinuation,
339 typename = std::enable_if_t<
340 std::is_constructible<continuation_type,
341 OtherContinuation&&>::value>>
promise_impl(promise_impl<OtherContinuation> other)342 promise_impl(promise_impl<OtherContinuation> other)
343 : state_(other.state_.has_value()
344 ? state_type(continuation_type(std::move(*other.state_)))
345 : state_type()) {}
346
347 // Creates a promise by taking the continuation from another promise,
348 // leaving the other promise empty.
349 promise_impl(promise_impl&& other) = default;
350
351 // Destroys the promise, releasing its continuation.
352 ~promise_impl() = default;
353
354 // Returns true if the promise is non-empty (has a valid continuation).
355 explicit operator bool() const { return state_.has_value(); }
356
357 // Invokes the promise's continuation.
358 //
359 // This method should be called by an executor to evaluate the promise.
360 // If the result's state is |result_state::pending| then the executor
361 // is responsible for arranging to invoke the promise's continuation
362 // again once it determines that it is possible to make progress
363 // towards completion of the promise encapsulated within the promise.
364 //
365 // Once the continuation returns a result with status |result_state::ok|
366 // or |result_state::error|, the promise is assigned an empty continuation.
367 //
368 // Asserts that the promise is non-empty.
operator()369 result_type operator()(context& context) {
370 assert(state_.has_value());
371 result_type result = (*state_)(context);
372 if (!result.is_pending())
373 state_.reset();
374 return result;
375 }
376
377 // Takes the promise's continuation, leaving it in an empty state.
378 // Asserts that the promise is non-empty.
take_continuation()379 continuation_type take_continuation() {
380 assert(state_.has_value());
381 auto continuation = std::move(state_.value());
382 state_.reset();
383 return continuation;
384 }
385
386 // Assigns the promise by taking the continuation from another promise,
387 // leaving the other promise empty.
388 promise_impl& operator=(promise_impl&& other) = default;
389
390 // Discards the promise's continuation, leaving it empty.
decltype(nullptr)391 promise_impl& operator=(decltype(nullptr)) {
392 state_.reset();
393 return *this;
394 }
395
396 // Assigns the promise's continuation.
397 promise_impl& operator=(continuation_type continuation) {
398 state_ = std::move(continuation);
399 return *this;
400 }
401
402 // Swaps the promises' continuations.
swap(promise_impl & other)403 void swap(promise_impl& other) {
404 using std::swap;
405 swap(state_, other.state_);
406 }
407
408 // Returns an unboxed promise which invokes the specified handler
409 // function after this promise completes (successfully or unsuccessfully),
410 // passing its result.
411 //
412 // The received result's state is guaranteed to be either
413 // |fit::result_state::ok| or |fit::result_state::error|, never
414 // |fit::result_state::pending|.
415 //
416 // |handler| is a callable object (such as a lambda) which consumes the
417 // result of this promise and returns a new result with any value type
418 // and error type. Must not be null.
419 //
420 // The handler must return one of the following types:
421 // - void
422 // - fit::result<new_value_type, new_error_type>
423 // - fit::ok<new_value_type>
424 // - fit::error<new_error_type>
425 // - fit::pending
426 // - fit::promise<new_value_type, new_error_type>
427 // - any callable or unboxed promise with the following signature:
428 // fit::result<new_value_type, new_error_type>(fit::context&)
429 //
430 // The handler must accept one of the following argument lists:
431 // - (result_type)
432 // - (result_type&)
433 // - (const result_type&)
434 // - (fit::context&, result_type)
435 // - (fit::context&, result_type&)
436 // - (fit::context&, const result_type&)
437 //
438 // Asserts that the promise is non-empty.
439 // This method consumes the promise's continuation, leaving it empty.
440 //
441 // EXAMPLE
442 //
443 // auto f = fit::make_promise(...)
444 // .then([] (fit::result<int, std::string> result)
445 // -> fit::result<std::string, void> {
446 // if (result.is_ok()) {
447 // printf("received value: %d\n", result.value());
448 // if (result.value() % 15 == 0)
449 // return ::fit::ok("fizzbuzz");
450 // if (result.value() % 3 == 0)
451 // return ::fit::ok("fizz");
452 // if (result.value() % 5 == 0)
453 // return ::fit::ok("buzz");
454 // return ::fit::ok(std::to_string(result.value()));
455 // } else {
456 // printf("received error: %s\n", result.error().c_str());
457 // return ::fit::error();
458 // }
459 // })
460 // .then(...);
461 //
462 template <typename ResultHandler>
463 promise_impl<::fit::internal::then_continuation<promise_impl, ResultHandler>>
then(ResultHandler handler)464 then(ResultHandler handler) {
465 static_assert(is_callable<ResultHandler>::value,
466 "ResultHandler must be a callable object.");
467
468 assert(!is_null(handler));
469 assert(state_.has_value());
470 return make_promise_with_continuation(
471 ::fit::internal::then_continuation<promise_impl, ResultHandler>(
472 std::move(*this), std::move(handler)));
473 }
474
475 // Returns an unboxed promise which invokes the specified handler
476 // function after this promise completes successfully, passing its
477 // resulting value.
478 //
479 // |handler| is a callable object (such as a lambda) which consumes the
480 // result of this promise and returns a new result with any value type
481 // but the same error type. Must not be null.
482 //
483 // The handler must return one of the following types:
484 // - void
485 // - fit::result<new_value_type, error_type>
486 // - fit::ok<new_value_type>
487 // - fit::error<error_type>
488 // - fit::pending
489 // - fit::promise<new_value_type, error_type>
490 // - any callable or unboxed promise with the following signature:
491 // fit::result<new_value_type, error_type>(fit::context&)
492 //
493 // The handler must accept one of the following argument lists:
494 // - (value_type)
495 // - (value_type&)
496 // - (const value_type&)
497 // - (fit::context&, value_type)
498 // - (fit::context&, value_type&)
499 // - (fit::context&, const value_type&)
500 //
501 // Asserts that the promise is non-empty.
502 // This method consumes the promise's continuation, leaving it empty.
503 //
504 // EXAMPLE
505 //
506 // auto f = fit::make_promise(...)
507 // .and_then([] (int value) {
508 // printf("received value: %d\n", value);
509 // if (value % 15 == 0)
510 // return ::fit::ok("fizzbuzz");
511 // if (value % 3 == 0)
512 // return ::fit::ok("fizz");
513 // if (value % 5 == 0)
514 // return ::fit::ok("buzz");
515 // return ::fit::ok(std::to_string(value));
516 // })
517 // .then(...);
518 //
519 template <typename ValueHandler>
520 promise_impl<::fit::internal::and_then_continuation<promise_impl, ValueHandler>>
and_then(ValueHandler handler)521 and_then(ValueHandler handler) {
522 static_assert(is_callable<ValueHandler>::value,
523 "ValueHandler must be a callable object.");
524
525 assert(!is_null(handler));
526 assert(state_.has_value());
527 return make_promise_with_continuation(
528 ::fit::internal::and_then_continuation<promise_impl, ValueHandler>(
529 std::move(*this), std::move(handler)));
530 }
531
532 // Returns an unboxed promise which invokes the specified handler
533 // function after this promise completes with an error, passing its
534 // resulting error.
535 //
536 // |handler| is a callable object (such as a lambda) which consumes the
537 // result of this promise and returns a new result with any error type
538 // but the same value type. Must not be null.
539 //
540 // The handler must return one of the following types:
541 // - void
542 // - fit::result<value_type, new_error_type>
543 // - fit::ok<value_type>
544 // - fit::error<new_error_type>
545 // - fit::pending
546 // - fit::promise<value_type, new_error_type>
547 // - any callable or unboxed promise with the following signature:
548 // fit::result<value_type, new_error_type>(fit::context&)
549 //
550 // The handler must accept one of the following argument lists:
551 // - (error_type)
552 // - (error_type&)
553 // - (const error_type&)
554 // - (fit::context&, error_type)
555 // - (fit::context&, error_type&)
556 // - (fit::context&, const error_type&)
557 //
558 // Asserts that the promise is non-empty.
559 // This method consumes the promise's continuation, leaving it empty.
560 //
561 // EXAMPLE
562 //
563 // auto f = fit::make_promise(...)
564 // .or_else([] (std::string error) {
565 // printf("received error: %s\n", error.c_str());
566 // return ::fit::error();
567 // })
568 // .then(...);
569 //
570 template <typename ErrorHandler>
571 promise_impl<::fit::internal::or_else_continuation<promise_impl, ErrorHandler>>
or_else(ErrorHandler handler)572 or_else(ErrorHandler handler) {
573 static_assert(is_callable<ErrorHandler>::value,
574 "ErrorHandler must be a callable object.");
575
576 assert(!is_null(handler));
577 assert(state_.has_value());
578 return make_promise_with_continuation(
579 ::fit::internal::or_else_continuation<promise_impl, ErrorHandler>(
580 std::move(*this), std::move(handler)));
581 }
582
583 // Returns an unboxed promise which invokes the specified handler
584 // function after this promise completes (successfully or unsuccessfully),
585 // passing it the promise's result then delivering the result onwards
586 // to the next promise once the handler returns.
587 //
588 // The handler receive a copy, const reference, or non-const reference
589 // depending on the signature of the handler's last argument.
590 //
591 // - Copies and const references are especially useful for inspecting a
592 // result mid-stream without modification, such as printing it for
593 // debugging.
594 // - Non-const references are especially useful for synchronously
595 // modifying a result mid-stream, such as clamping its bounds or
596 // injecting a default value.
597 //
598 // |handler| is a callable object (such as a lambda) which can examine
599 // or modify the incoming result. Unlike |then()|, the handler does
600 // not need to propagate the result onwards. Must not be null.
601 //
602 // The handler must return one of the following types:
603 // - void
604 //
605 // The handler must accept one of the following argument lists:
606 // - (result_type)
607 // - (result_type&)
608 // - (const result_type&)
609 // - (fit::context&, result_type)
610 // - (fit::context&, result_type&)
611 // - (fit::context&, const result_type&)
612 //
613 // Asserts that the promise is non-empty.
614 // This method consumes the promise's continuation, leaving it empty.
615 //
616 // EXAMPLE
617 //
618 // auto f = fit::make_promise(...)
619 // .inspect([] (const fit::result<int, std::string>& result) {
620 // if (result.is_ok())
621 // printf("received value: %d\n", result.value());
622 // else
623 // printf("received error: %s\n", result.error().c_str());
624 // })
625 // .then(...);
626 //
627 template <typename InspectHandler>
628 promise_impl<::fit::internal::inspect_continuation<promise_impl, InspectHandler>>
inspect(InspectHandler handler)629 inspect(InspectHandler handler) {
630 static_assert(is_callable<InspectHandler>::value,
631 "InspectHandler must be a callable object.");
632 static_assert(std::is_void<typename callable_traits<
633 InspectHandler>::return_type>::value,
634 "InspectHandler must return void.");
635
636 assert(!is_null(handler));
637 assert(state_.has_value());
638 return make_promise_with_continuation(
639 ::fit::internal::inspect_continuation<promise_impl, InspectHandler>(
640 std::move(*this), std::move(handler)));
641 }
642
643 // Returns an unboxed promise which discards the result of this promise
644 // once it completes, thereby always producing a successful result of
645 // type fit::result<void, void> regardless of whether this promise
646 // succeeded or failed.
647 //
648 // Asserts that the promise is non-empty.
649 // This method consumes the promise's continuation, leaving it empty.
650 //
651 // EXAMPLE
652 //
653 // auto f = fit::make_promise(...)
654 // .discard_result()
655 // .then(...);
656 //
657 promise_impl<::fit::internal::discard_result_continuation<promise_impl>>
discard_result()658 discard_result() {
659 assert(state_.has_value());
660 return make_promise_with_continuation(
661 ::fit::internal::discard_result_continuation<promise_impl>(
662 std::move(*this)));
663 }
664
665 // Applies a |wrapper| to the promise. Invokes the wrapper's |wrap()|
666 // method, passes the promise to the wrapper by value followed by any
667 // additional |args| passed to |wrap_with()|, then returns the wrapper's
668 // result.
669 //
670 // |Wrapper| is a type that implements a method called |wrap()| which
671 // accepts a promise as its argument and produces a wrapped result of
672 // any type, such as another promise.
673 //
674 // Asserts that the promise is non-empty.
675 // This method consumes the promise's continuation, leaving it empty.
676 //
677 // EXAMPLE
678 //
679 // In this example, |fit::sequencer| is a wrapper type that imposes
680 // FIFO execution order onto a sequence of wrapped promises.
681 //
682 // // This wrapper type is intended to be applied to
683 // // a sequence of promises so we store it in a variable.
684 // fit::sequencer seq;
685 //
686 // // This task consists of some amount of work that must be
687 // // completed sequentially followed by other work that can
688 // // happen in any order. We use |wrap_with()| to wrap the
689 // // sequential work with the sequencer.
690 // fit::promise<> perform_complex_task() {
691 // return fit::make_promise([] { /* do sequential work */ })
692 // .then([] (fit::result<> result) { /* this will also be wrapped */ })
693 // .wrap_with(seq)
694 // .then([] (fit::result<> result) { /* do more work */ });
695 // }
696 //
697 // This example can also be written without using |wrap_with()|.
698 // The behavior is equivalent but the syntax may seem more awkward.
699 //
700 // fit::sequencer seq;
701 //
702 // promise<> perform_complex_task() {
703 // return seq.wrap(
704 // fit::make_promise([] { /* sequential work */ })
705 // ).then([] (fit::result<> result) { /* more work */ });
706 // }
707 //
708 template <typename Wrapper, typename... Args>
decltype(auto)709 decltype(auto) wrap_with(Wrapper& wrapper, Args... args) {
710 assert(state_.has_value());
711 return wrapper.wrap(std::move(*this),
712 std::forward<Args>(args)...);
713 }
714
715 // Wraps the promise's continuation into a |fit::function|.
716 //
717 // A boxed promise is easier to store and pass around than the unboxed
718 // promises produced by |fit::make_promise()| and combinators, though boxing
719 // may incur a heap allocation.
720 //
721 // It is a good idea to defer boxing the promise until after all
722 // desired combinators have been applied to prevent unnecessary heap
723 // allocation during intermediate states of the promise's construction.
724 //
725 // Returns an empty promise if this promise is empty.
726 // This method consumes the promise's continuation, leaving it empty.
727 //
728 // EXAMPLE
729 //
730 // // f's is a fit::promise_impl<> whose continuation contains an
731 // // anonymous type (the lambda)
732 // auto f = fit::make_promise([] {});
733 //
734 // // g's type will be fit::promise<> due to boxing
735 // auto boxed_f = f.box();
736 //
737 // // alternately, we can get exactly the same effect by assigning
738 // // the unboxed promise to a variable of a named type instead of
739 // // calling box()
740 // fit::promise<> boxed_f = std::move(f);
741 //
box()742 promise_impl<function<result_type(context&)>> box() {
743 return std::move(*this);
744 }
745
746 promise_impl(const promise_impl&) = delete;
747 promise_impl& operator=(const promise_impl&) = delete;
748
749 private:
750 template <typename>
751 friend class promise_impl;
752
753 state_type state_;
754 };
755
756 template <typename Continuation>
swap(promise_impl<Continuation> & a,promise_impl<Continuation> & b)757 void swap(promise_impl<Continuation>& a,
758 promise_impl<Continuation>& b) {
759 a.swap(b);
760 }
761
762 template <typename Continuation>
763 bool operator==(const promise_impl<Continuation>& f,
764 decltype(nullptr)) {
765 return !f;
766 }
767 template <typename Continuation>
768 bool operator==(decltype(nullptr),
769 const promise_impl<Continuation>& f) {
770 return !f;
771 }
772 template <typename Continuation>
773 bool operator!=(const promise_impl<Continuation>& f,
774 decltype(nullptr)) {
775 return !!f;
776 }
777 template <typename Continuation>
778 bool operator!=(decltype(nullptr),
779 const promise_impl<Continuation>& f) {
780 return !!f;
781 }
782
783 // Makes a promise containing the specified continuation.
784 //
785 // This function is used for making a promises given a callable object
786 // that represents a valid continuation type. In contrast,
787 // |fit::make_promise()| supports a wider range of types and should be
788 // preferred in most situations.
789 //
790 // |Continuation| is a callable object with the signature
791 // fit::result<V, E>(fit::context&).
792 template <typename Continuation>
make_promise_with_continuation(Continuation continuation)793 inline promise_impl<Continuation> make_promise_with_continuation(
794 Continuation continuation) {
795 return promise_impl<Continuation>(std::move(continuation));
796 }
797
798 // Returns an unboxed promise that wraps the specified handler.
799 // The type of the promise's result is inferred from the handler's result.
800 //
801 // |handler| is a callable object (such as a lambda. Must not be null.
802 //
803 // The handler must return one of the following types:
804 // - void
805 // - fit::result<value_type, error_type>
806 // - fit::ok<value_type>
807 // - fit::error<error_type>
808 // - fit::pending
809 // - fit::promise<value_type, error_type>
810 // - any callable or unboxed promise with the following signature:
811 // fit::result<value_type, error_type>(fit::context&)
812 //
813 // The handler must accept one of the following argument lists:
814 // - ()
815 // - (fit::context&)
816 //
817 // See documentation of |fit::promise| for more information.
818 //
819 // SYNOPSIS
820 //
821 // |Handler| is the handler function type. It is typically inferred by the
822 // compiler from the |handler| argument.
823 //
824 // EXAMPLE
825 //
826 // enum class weather_type { sunny, glorious, cloudy, eerie, ... };
827 //
828 // weather_type look_outside() { ... }
829 // void wait_for_tomorrow(fit::suspended_task task) {
830 // ... arrange to call task.resume_task() tomorrow ...
831 // }
832 //
833 // fit::promise<weather_type, std::string> wait_for_good_weather(int max_days) {
834 // return fit::make_promise([days_left = max_days] (fit::context context&) mutable
835 // -> fit::result<int, std::string> {
836 // weather_type weather = look_outside();
837 // if (weather == weather_type::sunny || weather == weather_type::glorious)
838 // return fit::ok(weather);
839 // if (days_left > 0) {
840 // wait_for_tomorrow(context.suspend_task());
841 // return fit::pending();
842 // }
843 // days_left--;
844 // return fit::error("nothing but grey skies");
845 // });
846 // }
847 //
848 // auto f = wait_for_good_weather(7)
849 // .and_then([] (weather_type weather) { ... })
850 // .or_else([] (std::string error) { ... });
851 //
852 template <typename PromiseHandler>
853 inline promise_impl<::fit::internal::context_handler_invoker<PromiseHandler>>
make_promise(PromiseHandler handler)854 make_promise(PromiseHandler handler) {
855 static_assert(is_callable<PromiseHandler>::value,
856 "PromiseHandler must be a callable object.");
857
858 assert(!is_null(handler));
859 return make_promise_with_continuation(
860 ::fit::internal::promise_continuation<PromiseHandler>(
861 std::move(handler)));
862 }
863
864 // Jointly evaluates zero or more promises.
865 // Returns a promise that produces a std::tuple<> containing the result
866 // of each promise once they all complete.
867 //
868 // EXAMPLE
869 //
870 // auto get_random_number() {
871 // return fit::make_promise([] { return rand() % 10 });
872 // }
873 //
874 // auto get_random_product() {
875 // auto f = get_random_number();
876 // auto g = get_random_number();
877 // return fit::join_promises(std::move(f), std::move(g))
878 // .and_then([] (std::tuple<fit::result<int>, fit::result<int>> results) {
879 // return fit::ok(results.get<0>.value() + results.get<1>.value());
880 // });
881 // }
882 //
883 template <typename... Promises>
884 inline promise_impl<::fit::internal::join_continuation<Promises...>>
join_promises(Promises...promises)885 join_promises(Promises... promises) {
886 return make_promise_with_continuation(
887 ::fit::internal::join_continuation<Promises...>(std::move(promises)...));
888 }
889
890 // Describes the status of a future.
891 enum class future_state {
892 // The future neither holds a result nor a promise that could produce a result.
893 // An empty future cannot make progress until a promise or result is assigned to it.
894 empty,
895 // The future holds a promise that may eventually produce a result but
896 // it currently doesn't have a result. The future's promise must be
897 // invoked in order to make progress from this state.
898 pending,
899 // The future holds a successful result.
900 ok,
901 // The future holds an error result.
902 error
903 };
904
905 // A |fit::future| holds onto a |fit::promise| until it has completed then
906 // provides access to its |fit::result|.
907 //
908 // SYNOPSIS
909 //
910 // |V| is the type of value produced when the completes successfully.
911 // Defaults to |void|.
912 //
913 // |E| is the type of error produced when the completes with an error.
914 // Defaults to |void|.
915 //
916 // THEORY OF OPERATION
917 //
918 // A future has a single owner who is responsible for setting its promise
919 // or result and driving its execution. Unlike |fit::promise|, a future retains
920 // the result produced by completion of its asynchronous task. Result retention
921 // eases the implementation of combined tasks that need to await the results
922 // of other tasks before proceeding.
923 //
924 // See the example for details.
925 //
926 // A future can be in one of four states, depending on whether it holds...
927 // - a successful result: |fit::future_state::ok|
928 // - an error result: |fit::future_state::error|
929 // - a promise that may eventually produce a result: |fit::future_state::pending|
930 // - neither: |fit::future_state_empty|
931 //
932 // On its own, a future is "inert"; it only makes progress in response to
933 // actions taken by its owner. The state of the future never changes
934 // spontaneously or concurrently.
935 //
936 // When the future's state is |fit::future_state::empty|, its owner is
937 // responsible for setting the future's promise or result thereby moving the
938 // future into the pending or ready state.
939 //
940 // When the future's state is |fit::future_state::pending|, its owner is
941 // responsible for calling the future's |operator()| to invoke the promise.
942 // If the promise completes and returns a result, the future will transition
943 // to the ok or error state according to the result. The promise itself will
944 // then be destroyed since it has fulfilled its purpose.
945 //
946 // When the future's state is |fit::future_state::ok|, its owner is responsible
947 // for consuming the stored value using |value()|, |take_value()|,
948 // |result()|, |take_result()|, or |take_ok_result()|.
949 //
950 // When the future's state is |fit::future_state::error|, its owner is
951 // responsible for consuming the stored error using |error()|, |take_error()|,
952 // |result()|, |take_result()|, or |take_error_result()|.
953 //
954 // See also |fit::promise| for more information about promises and their
955 // execution.
956 //
957 // EXAMPLE
958 //
959 // - https://fuchsia.googlesource.com/zircon/+/master/system/utest/fit/examples/promise_example2.cpp
960 template <typename V = void, typename E = void>
961 using future = future_impl<promise<V, E>>;
962
963 // Future implementation details.
964 // See |fit::future| documentation for more information.
965 template <typename Promise>
966 class future_impl final {
967 public:
968 // The type of promise held by the future.
969 using promise_type = Promise;
970
971 // The promise's result type.
972 // Equivalent to fit::result<value_type, error_type>.
973 using result_type = typename Promise::result_type;
974
975 // The type of value produced when the promise completes successfully.
976 // May be void.
977 using value_type = typename Promise::value_type;
978
979 // The type of value produced when the promise completes with an error.
980 // May be void.
981 using error_type = typename Promise::error_type;
982
983 // Creates a future in the empty state.
984 future_impl() = default;
future_impl(decltype (nullptr))985 future_impl(decltype(nullptr)) {}
986
987 // Creates a future and assigns a promise to compute its result.
988 // If the promise is empty, the future enters the empty state.
989 // Otherwise the future enters the pending state.
future_impl(promise_type promise)990 explicit future_impl(promise_type promise) {
991 if (promise) {
992 state_.template emplace<1>(std::move(promise));
993 }
994 }
995
996 // Creates a future and assigns its result.
997 // If the result is pending, the future enters the empty state.
998 // Otherwise the future enters the ok or error state.
future_impl(result_type result)999 explicit future_impl(result_type result) {
1000 if (result) {
1001 state_.template emplace<2>(std::move(result));
1002 }
1003 }
1004
1005 // Moves from another future, leaving the other one in an empty state.
future_impl(future_impl && other)1006 future_impl(future_impl&& other)
1007 : state_(std::move(other.state_)) {
1008 other.state_.template emplace<0>();
1009 }
1010
1011 // Destroys the promise, releasing its promise and result (if any).
1012 ~future_impl() = default;
1013
1014 // Returns the state of the future: empty, pending, ok, or error.
state()1015 future_state state() const {
1016 switch (state_.index()) {
1017 case 0:
1018 return future_state::empty;
1019 case 1:
1020 return future_state::pending;
1021 case 2:
1022 return state_.template get<2>().is_ok()
1023 ? future_state::ok
1024 : future_state::error;
1025 }
1026 __builtin_unreachable();
1027 }
1028
1029 // Returns true if the future's state is not |fit::future_state::empty|:
1030 // it either holds a result or holds a promise that can be invoked to make
1031 // progress towards obtaining a result.
1032 explicit operator bool() const { return !is_empty(); }
1033
1034 // Returns true if the future's state is |fit::future_state::empty|:
1035 // it does not hold a result or a promise so it cannot make progress.
is_empty()1036 bool is_empty() const { return state() == fit::future_state::empty; }
1037
1038 // Returns true if the future's state is |fit::future_state::pending|:
1039 // it does not hold a result yet but it does hold a promise that can be invoked
1040 // to make progress towards obtaining a result.
is_pending()1041 bool is_pending() const { return state() == fit::future_state::pending; }
1042
1043 // Returns true if the future's state is |fit::future_state::ok|:
1044 // it holds a value that can be retrieved using |value()|, |take_value()|,
1045 // |result()|, |take_result()|, or |take_ok_result()|.
is_ok()1046 bool is_ok() const { return state() == fit::future_state::ok; }
1047
1048 // Returns true if the future's state is |fit::future_state::error|:
1049 // it holds an error that can be retrieved using |error()|, |take_error()|,
1050 // |result()|, |take_result()|, or |take_error_result()|.
is_error()1051 bool is_error() const { return state() == fit::future_state::error; }
1052
1053 // Returns true if the future's state is either |fit::future_state::ok| or
1054 // |fit::future_state::error|.
is_ready()1055 bool is_ready() const { return state_.index() == 2; }
1056
1057 // Evaluates the future and returns true if its result is ready.
1058 // Asserts that the future is not empty.
1059 //
1060 // If the promise completes and returns a result, the future will transition
1061 // to the ok or error state according to the result. The promise itself will
1062 // then be destroyed since it has fulfilled its purpose.
operator()1063 bool operator()(fit::context& context) {
1064 switch (state_.index()) {
1065 case 0:
1066 return false;
1067 case 1: {
1068 result_type result = state_.template get<1>()(context);
1069 if (!result)
1070 return false;
1071 state_.template emplace<2>(std::move(result));
1072 return true;
1073 }
1074 case 2:
1075 return true;
1076 }
1077 __builtin_unreachable();
1078 }
1079
1080 // Gets a reference to the future's promise.
1081 // Asserts that the future's state is |fit::future_state::pending|.
promise()1082 const promise_type& promise() const {
1083 assert(is_pending());
1084 return state_.template get<1>();
1085 }
1086
1087 // Takes the future's promise, leaving it in an empty state.
1088 // Asserts that the future's state is |fit::future_state::pending|.
take_promise()1089 promise_type take_promise() {
1090 assert(is_pending());
1091 auto promise = std::move(state_.template get<1>());
1092 state_.template emplace<0>();
1093 return promise;
1094 }
1095
1096 // Gets a reference to the future's result.
1097 // Asserts that the future's state is |fit::future_state::ok| or
1098 // |fit::future_state::error|.
result()1099 result_type& result() {
1100 assert(is_ready());
1101 return state_.template get<2>();
1102 }
result()1103 const result_type& result() const {
1104 assert(is_ready());
1105 return state_.template get<2>();
1106 }
1107
1108 // Takes the future's result, leaving it in an empty state.
1109 // Asserts that the future's state is |fit::future_state::ok| or
1110 // |fit::future_state::error|.
take_result()1111 result_type take_result() {
1112 assert(is_ready());
1113 auto result = std::move(state_.template get<2>());
1114 state_.template emplace<0>();
1115 return result;
1116 }
1117
1118 // Gets a reference to the future's value.
1119 // Asserts that the future's state is |fit::future_state::ok|.
1120 template <typename R = value_type,
1121 typename = std::enable_if_t<!std::is_void<R>::value>>
value()1122 R& value() {
1123 assert(is_ok());
1124 return state_.template get<2>().value();
1125 }
1126 template <typename R = value_type,
1127 typename = std::enable_if_t<!std::is_void<R>::value>>
value()1128 const R& value() const {
1129 assert(is_ok());
1130 return state_.template get<2>().value();
1131 }
1132
1133 // Takes the future's value, leaving it in an empty state.
1134 // Asserts that the future's state is |fit::future_state::ok|.
1135 template <typename R = value_type,
1136 typename = std::enable_if_t<!std::is_void<R>::value>>
take_value()1137 R take_value() {
1138 assert(is_ok());
1139 auto value = state_.template get<2>().take_value();
1140 state_.template emplace<0>();
1141 return value;
1142 }
take_ok_result()1143 ok_result<value_type> take_ok_result() {
1144 assert(is_ok());
1145 auto result = state_.template get<2>().take_ok_result();
1146 state_.template emplace<0>();
1147 return result;
1148 }
1149
1150 // Gets a reference to the future's error.
1151 // Asserts that the future's state is |fit::future_state::error|.
1152 template <typename R = error_type,
1153 typename = std::enable_if_t<!std::is_void<R>::value>>
error()1154 R& error() {
1155 assert(is_error());
1156 return state_.template get<2>().error();
1157 }
1158 template <typename R = error_type,
1159 typename = std::enable_if_t<!std::is_void<R>::value>>
error()1160 const R& error() const {
1161 assert(is_error());
1162 return state_.template get<2>().error();
1163 }
1164
1165 // Takes the future's error, leaving it in an empty state.
1166 // Asserts that the future's state is |fit::future_state::error|.
1167 template <typename R = error_type,
1168 typename = std::enable_if_t<!std::is_void<R>::value>>
take_error()1169 R take_error() {
1170 assert(is_error());
1171 auto error = state_.template get<2>().take_error();
1172 state_.template emplace<0>();
1173 return error;
1174 }
take_error_result()1175 error_result<error_type> take_error_result() {
1176 assert(is_error());
1177 auto result = state_.template get<2>().take_error_result();
1178 state_.template emplace<0>();
1179 return result;
1180 }
1181
1182 // Move assigns from another future, leaving the other one in an empty state.
1183 future_impl& operator=(future_impl&& other) = default;
1184
1185 // Discards the future's promise and result, leaving it empty.
decltype(nullptr)1186 future_impl& operator=(decltype(nullptr)) {
1187 state_.template emplace<0>();
1188 return *this;
1189 }
1190
1191 // Assigns a promise to compute the future's result.
1192 // If the promise is empty, the future enters the empty state.
1193 // Otherwise the future enters the pending state.
1194 future_impl& operator=(promise_type promise) {
1195 if (promise) {
1196 state_.template emplace<1>(std::move(promise));
1197 } else {
1198 state_.template emplace<0>();
1199 }
1200 return *this;
1201 }
1202
1203 // Assigns the future's result.
1204 // If the result is pending, the future enters the empty state.
1205 // Otherwise the future enters the ok or error state.
1206 future_impl& operator=(result_type result) {
1207 if (result) {
1208 state_.template emplace<2>(std::move(result));
1209 } else {
1210 state_.template emplace<0>();
1211 }
1212 return *this;
1213 }
1214
1215 // Swaps the futures' contents.
swap(future_impl & other)1216 void swap(future_impl& other) {
1217 using std::swap;
1218 swap(state_, other.state_);
1219 }
1220
1221 future_impl(const future_impl&) = delete;
1222 future_impl& operator=(const future_impl&) = delete;
1223
1224 private:
1225 ::fit::internal::variant<::fit::internal::monostate,
1226 promise_type, result_type>
1227 state_;
1228 };
1229
1230 template <typename Promise>
swap(future_impl<Promise> & a,future_impl<Promise> & b)1231 void swap(future_impl<Promise>& a, future_impl<Promise>& b) {
1232 a.swap(b);
1233 }
1234
1235 template <typename Promise>
1236 bool operator==(const future_impl<Promise>& f, decltype(nullptr)) {
1237 return !f;
1238 }
1239 template <typename Promise>
1240 bool operator==(decltype(nullptr), const future_impl<Promise>& f) {
1241 return !f;
1242 }
1243 template <typename Promise>
1244 bool operator!=(const future_impl<Promise>& f, decltype(nullptr)) {
1245 return !!f;
1246 }
1247 template <typename Promise>
1248 bool operator!=(decltype(nullptr), const future_impl<Promise>& f) {
1249 return !!f;
1250 }
1251
1252 // Makes a future containing the specified promise.
1253 template <typename Promise>
make_future(Promise promise)1254 future_impl<Promise> make_future(Promise promise) {
1255 return future_impl<Promise>(std::move(promise));
1256 }
1257
1258 // A pending task holds a |fit::promise| that can be scheduled to run on
1259 // a |fit::executor| using |fit::executor::schedule_task()|.
1260 //
1261 // An executor repeatedly invokes a pending task until it returns true,
1262 // indicating completion. Note that the promise's resulting value or error
1263 // is discarded since it is not meaningful to the executor. If you need
1264 // to consume the result, use a combinator such as |fit::pending::then()|
1265 // to capture it prior to wrapping the promise into a pending task.
1266 //
1267 // See documentation of |fit::promise| for more information.
1268 class pending_task final {
1269 public:
1270 // The type of promise held by this task.
1271 using promise_type = promise<void, void>;
1272
1273 // Creates an empty pending task without a promise.
1274 pending_task() = default;
1275
1276 // Creates a pending task that wraps an already boxed promise that returns
1277 // |fit::result<void, void>|.
pending_task(promise_type promise)1278 pending_task(promise_type promise)
1279 : promise_(std::move(promise)) {}
1280
1281 // Creates a pending task that wraps any kind of promise, boxed or unboxed,
1282 // regardless of its result type and with any context that is assignable
1283 // from this task's context type.
1284 template <typename Continuation>
pending_task(promise_impl<Continuation> promise)1285 pending_task(promise_impl<Continuation> promise)
1286 : promise_(promise ? promise.discard_result().box() : promise_type()) {}
1287
1288 pending_task(pending_task&&) = default;
1289 pending_task& operator=(pending_task&&) = default;
1290
1291 // Destroys the pending task, releasing its promise.
1292 ~pending_task() = default;
1293
1294 // Returns true if the pending task is non-empty (has a valid promise).
1295 explicit operator bool() const { return !!promise_; }
1296
1297 // Evaluates the pending task.
1298 // If the task completes (returns a non-pending result), the task reverts
1299 // to an empty state (because the promise it holds has reverted to an empty
1300 // state) and returns true.
1301 // It is an error to invoke this method if the pending task is empty.
operator()1302 bool operator()(fit::context& context) {
1303 return !promise_(context).is_pending();
1304 }
1305
1306 // Extracts the pending task's promise.
take_promise()1307 promise_type take_promise() {
1308 return std::move(promise_);
1309 }
1310
1311 pending_task(const pending_task&) = delete;
1312 pending_task& operator=(const pending_task&) = delete;
1313
1314 private:
1315 promise_type promise_;
1316 };
1317
1318 // Execution context for an asynchronous task, such as a |fit::promise|,
1319 // |fit::future|, or |fit::pending_task|.
1320 //
1321 // When a |fit::executor| executes a task, it provides the task with an
1322 // execution context which enables the task to communicate with the
1323 // executor and manage its own lifecycle. Specialized executors may subclass
1324 // |fit::context| and offer additional methods beyond those which are
1325 // defined here, such as to provide access to platform-specific features
1326 // supported by the executor.
1327 //
1328 // The context provided to a task is only valid within the scope of a single
1329 // invocation; the task must not retain a reference to the context across
1330 // invocations.
1331 //
1332 // See documentation of |fit::promise| for more information.
1333 class context {
1334 public:
1335 // Gets the executor that is running the task, never null.
1336 virtual class executor* executor() const = 0;
1337
1338 // Obtains a handle that can be used to resume the task after it has been
1339 // suspended.
1340 //
1341 // Clients should call this method before returning |fit::pending()| from
1342 // the task. See documentation on |fit::executor|.
1343 virtual suspended_task suspend_task() = 0;
1344
1345 // Converts this context to a derived context type.
1346 template <typename Context,
1347 typename = std::enable_if_t<std::is_base_of<context, Context>::value>>
as()1348 Context& as() & {
1349 // TODO(CP-163): We should perform a run-time type check here rather
1350 // than blindly casting. That's why this method exists.
1351 return static_cast<Context&>(*this);
1352 }
1353
1354 protected:
1355 virtual ~context() = default;
1356 };
1357
1358 // An abstract interface for executing asynchronous tasks, such as promises,
1359 // represented by |fit::pending_task|.
1360 //
1361 // EXECUTING TASKS
1362 //
1363 // An executor evaluates its tasks incrementally. During each iteration
1364 // of the executor's main loop, it invokes the next task from its ready queue.
1365 //
1366 // If the task returns true, then the task is deemed to have completed.
1367 // The executor removes the tasks from its queue and destroys it since there
1368 // it nothing left to do.
1369 //
1370 // If the task returns false, then the task is deemed to have voluntarily
1371 // suspended itself pending some event that it is awaiting. Prior to
1372 // returning, the task should acquire at least one |fit::suspended_task|
1373 // handle from its execution context using |fit::context::suspend_task()|
1374 // to provide a means for the task to be resumed once it can make forward
1375 // progress again.
1376 //
1377 // Once the suspended task is resumed with |fit::suspended_task::resume()|, it
1378 // is moved back to the ready queue and it will be invoked again during a later
1379 // iteration of the executor's loop.
1380 //
1381 // If all |fit::suspended_task| handles for a given task are destroyed without
1382 // the task ever being resumed then the task is also destroyed since there
1383 // would be no way for the task to be resumed from suspension. We say that
1384 // such a task has been "abandoned".
1385 //
1386 // The executor retains single-ownership of all active and suspended tasks.
1387 // When the executor is destroyed, all of its remaining tasks are also
1388 // destroyed.
1389 //
1390 // Please read |fit::promise| for a more detailed explanation of the
1391 // responsibilities of tasks and executors.
1392 //
1393 // NOTES FOR IMPLEMENTORS
1394 //
1395 // This interface is designed to support a variety of different executor
1396 // implementations. For example, one implementation might run its tasks on
1397 // a single thread whereas another might dispatch them on an event-driven
1398 // message loop or use a thread pool.
1399 //
1400 // See also |fit::single_threaded_executor| for a concrete implementation.
1401 class executor {
1402 public:
1403 // Destroys the executor along with all of its remaining scheduled tasks
1404 // that have yet to complete.
1405 virtual ~executor() = default;
1406
1407 // Schedules a task for eventual execution by the executor.
1408 //
1409 // This method is thread-safe.
1410 virtual void schedule_task(pending_task task) = 0;
1411 };
1412
1413 // Represents a task that is awaiting resumption.
1414 //
1415 // This object has RAII semantics. If the task is not resumed by at least
1416 // one holder of its |suspended_task| handles, then it will be destroyed
1417 // by the executor since it is no longer possible for the task to make
1418 // progress. The task is said have been "abandoned".
1419 //
1420 // See documentation of |fit::executor| for more information.
1421 class suspended_task final {
1422 public:
1423 // A handle that grants the capability to resume a suspended task.
1424 // Each issued ticket must be individually resolved.
1425 using ticket = uint64_t;
1426
1427 // The resolver mechanism implements a lightweight form of reference
1428 // counting for tasks that have been suspended.
1429 //
1430 // When a suspended task is created in a non-empty state, it receives
1431 // a pointer to a resolver interface and a ticket. The ticket is
1432 // a one-time-use handle that represents the task that was suspended
1433 // and provides a means to resume it. The |suspended_task| class ensures
1434 // that every ticket is precisely accounted for.
1435 //
1436 // When |suspended_task::resume_task()| is called on an instance with
1437 // a valid ticket, the resolver's |resolve_ticket()| method is invoked
1438 // passing the ticket's value along with *true* to resume the task. This
1439 // operation consumes the ticket so the |suspended_task| transitions to
1440 // an empty state. The ticket and resolver cannot be used again by
1441 // this |suspended_task| instance.
1442 //
1443 // Similarly, when |suspended_task::reset()| is called on an instance with
1444 // a valid ticket or when the task goes out of scope on such an instance,
1445 // the resolver's |resolve_ticket()| method is invoked but this time passes
1446 // *false* to not resume the task. As before, the ticket is consumed.
1447 //
1448 // Finally, when the |suspended_task| is copied, its ticket is duplicated
1449 // using |duplicate_ticket()| resulting in two tickets, both of which
1450 // must be individually resolved.
1451 //
1452 // Resuming a task that has already been resumed has no effect.
1453 // Conversely, a task is considered "abandoned" if all of its tickets
1454 // have been resolved without it ever being resumed. See documentation
1455 // of |fit::promise| for more information.
1456 //
1457 // The methods of this class are safe to call from any thread, including
1458 // threads that may not be managed by the task's executor.
1459 class resolver {
1460 public:
1461 // Duplicates the provided ticket, returning a new ticket.
1462 // Note: The new ticket may have the same numeric value as the
1463 // original ticket but should be considered a distinct instance
1464 // that must be separately resolved.
1465 virtual ticket duplicate_ticket(ticket ticket) = 0;
1466
1467 // Consumes the provided ticket, optionally resuming its associated task.
1468 // The provided ticket must not be used again.
1469 virtual void resolve_ticket(ticket ticket, bool resume_task) = 0;
1470
1471 protected:
1472 virtual ~resolver() = default;
1473 };
1474
suspended_task()1475 suspended_task()
1476 : resolver_(nullptr), ticket_(0) {}
1477
suspended_task(resolver * resolver,ticket ticket)1478 suspended_task(resolver* resolver, ticket ticket)
1479 : resolver_(resolver), ticket_(ticket) {}
1480
1481 suspended_task(const suspended_task& other);
1482 suspended_task(suspended_task&& other);
1483
1484 // Releases the task without resumption.
1485 //
1486 // Does nothing if this object does not hold a ticket.
1487 ~suspended_task();
1488
1489 // Returns true if this object holds a ticket for a suspended task.
1490 explicit operator bool() const { return resolver_ != nullptr; }
1491
1492 // Asks the task's executor to resume execution of the suspended task
1493 // if it has not already been resumed or completed. Also releases
1494 // the task's ticket as a side-effect.
1495 //
1496 // Clients should call this method when it is possible for the task to
1497 // make progress; for example, because some event the task was
1498 // awaiting has occurred. See documentation on |fit::executor|.
1499 //
1500 // Does nothing if this object does not hold a ticket.
resume_task()1501 void resume_task() { resolve(true); }
1502
1503 // Releases the suspended task without resumption.
1504 //
1505 // Does nothing if this object does not hold a ticket.
reset()1506 void reset() { resolve(false); }
1507
1508 // Swaps suspended tasks.
1509 void swap(suspended_task& other);
1510
1511 suspended_task& operator=(const suspended_task& other);
1512 suspended_task& operator=(suspended_task&& other);
1513
1514 private:
1515 void resolve(bool resume_task);
1516
1517 resolver* resolver_;
1518 ticket ticket_;
1519 };
1520
swap(suspended_task & a,suspended_task & b)1521 inline void swap(suspended_task& a, suspended_task& b) {
1522 a.swap(b);
1523 }
1524
1525 } // namespace fit
1526
1527 #endif // LIB_FIT_PROMISE_H_
1528