template <typename V = void, typename E = void>
class bridge
Defined at line 136 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
A bridge is a building block for asynchronous control flow that is formed
by the association of two distinct participants: a completer and a consumer.
- The completer is responsible for reporting completion of an asynchronous
task and providing its result. See |completer| and |fpromise::completer|.
- The consumer is responsible for consuming the result of the asynchronous
task. See |consumer| and |fpromise::consumer|.
This class is often used for binding a |fpromise::promise| to a callback,
facilitating interoperation of promises with functions that asynchronously
report their result via a callback function. It can also be used more
generally anytime it is necessary to decouple completion of an asynchronous
task from consumption of its result (possibly on different threads).
The completer and consumer each possesses a unique capability that can
be exercised at most once during their association: the asynchronous
task represented by a bridge can be completed at most once and its
result can be consumed at most once. This property is enforced by
a single-ownership model for completers and consumers.
The completion capability has a single owner represented by |fpromise::completer|.
Its owner may exercise the capability to complete the task (provide its result),
it may transfer the capability by moving it to another completer instance,
or it may cause the asynchronous task to be "abandoned" by discarding the
capability, implying that the task can never produce a result. When this
occurs, the associated consumer's |fpromise::consumer::was_abandoned()| method
will return true and the consumer will not obtain any result from the task.
See |fpromise::consumer::promise()| and |fpromise::consumer::promise_or()| for
details on how abandonment of the task can be handled by the consumer.
The consumption capability has a single owner represented by |fpromise::consumer|.
Its owner may exercise the capability to consume the task's result (as a
promise), it may transfer the capability by moving it to another consumer
instance, or it may cause the asynchronous task to be "canceled" by
discarding the capability, implying that the task's result can never be
consumed. When this occurs, the associated completer's
|fpromise::completer::was_canceled()| method will return true and the task's
eventual result (if any) will be silently discarded.
DECOUPLING
See |fpromise::schedule_for_consumer| for a helper which uses a bridge to
decouple completion and consumption of a task's result so they can be
performed on different executors.
SYNOPSIS
|V| is the type of value produced when the task completes successfully.
Use |std::tuple
<Args
...>| if the task produces multiple values, such as
when you intend to bind the task's completer to a callback with multiple
arguments using |fpromise::completer::bind_tuple()|.
Defaults to |void|.
|E| is the type of error produced when the task completes with an error.
Defaults to |void|.
EXAMPLE
Imagine a File I/O library offers a callback-based asynchronous reading
function. We suppose that the read handling code will invoke the
callback upon completion. The library's API might look a bit like this:
using read_callback = fit::function
<void
(size_t bytes_read)>;
void read_async(size_t num_bytes, uint8_t* buffer, read_callback cb);
Here's how we can adapt the library's "read_async" function to a
|fpromise::promise| by binding its callback to a bridge:
fpromise::promise
<size
_t> promise_read(uint8_t* buffer, size_t num_bytes) {
fpromise::bridge
<size
_t> bridge;
read_async(num_bytes, buffer, bridge.completer.bind());
return bridge.consumer.promise_or(::fpromise::error());
}
Finally we can chain additional asynchronous tasks to be performed upon
completion of the promised read:
uint8_t buffer[4096];
void my_program(fpromise::executor* executor) {
auto promise = promise_read(buffer, sizeof(buffer))
.and_then([] (const size_t
&
bytes_read) {
// consume contents of buffer
})
.or_else() {
// handle error case
});
executor->schedule_task(std::move(promise));
}
Similarly, suppose the File I/O library offers a callback-based asynchronous
writing function that can return a variety of errors encoded as negative
sizes. Here's how we might decode those errors uniformly into |fpromise::result|
allowing them to be handled using combinators such as |or_else|.
using write_callback = fit::function
<void
(size_t bytes_written, int error)>;
void write_async(size_t num_bytes, uint8_t* buffer, write_callback cb);
fpromise::promise
<size
_t, int> promise_write(uint8_t* buffer, size_t num_bytes) {
fpromise::bridge
<size
_t, int> bridge;
write_async(num_bytes, buffer,
[completer = std::move(bridge.completer)](size_t bytes_written, int error) {
if (bytes_written == 0) {
completer.complete_error(error);
return;
}
completer.complete_ok(bytes_written);
});
return bridge.consumer.promise_or(::fpromise::error(ERR_ABANDONED));
}
uint8_t buffer[4096];
void my_program(fpromise::executor* executor) {
auto promise = promise_write(buffer, sizeof(buffer))
.and_then([] (const size_t
&
bytes_written) {
// consume contents of buffer
})
.or_else(const int
&
error) {
// handle error case
});
executor->schedule_task(std::move(promise));
}
See documentation of |fpromise::promise| for more information.
Public Members
completer_type completer
consumer_type consumer
Public Methods
void bridge<V, E> ()
Creates a bridge representing a new asynchronous task formed by the
association of a completer and consumer.
Defined at line 146 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
void bridge<V, E> (bridge<V, E> && other)
Defined at line 150 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
void bridge<V, E> (const bridge<V, E> & other)
Defined at line 151 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
void ~bridge<V, E> ()
Defined at line 152 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
bridge<V, E> & operator= (bridge<V, E> && other)
Defined at line 154 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h
bridge<V, E> & operator= (const bridge<V, E> & other)
Defined at line 155 of file ../../sdk/lib/fit-promise/include/lib/fpromise/bridge.h