7.0 KiB
| title |
|---|
| future / promise |
{{< callout type="info">}}
Header: future.h
From: 20.50.0
{{< /callout >}}
A lightweight, heap-free future / promise pair for passing a single result from a producer (e.g. an ISR, a
thread or an RPC response handler) to a consumer.
Unlike std::future/std::promise, the shared state is not allocated. It is an etl::shared_state<T> object
whose storage and lifetime are managed by the user, for example as an element of a fixed-size pending-request table.
etl::future<T> and etl::promise<T> are non-owning handles to it.
template <typename T>
class shared_state;
template <typename T>
class future;
template <typename T>
class promise;
All three are specialised for void, where there is no value, only a ready notification, and for references
(T&), where a pointer to the referenced object is stored. T must not be an array type.
Differences from the standard library
etl::future<T>has the semantics ofstd::shared_future<T>: it is copyable, andget()does not consume the value, so it may be called more than once, by every copy.get()returnsconst T&(R&forfuture<R&>).etl::promise<T>is, likestd::promise<T>, move-only (C++11) or non-copyable (C++03).get()does not block. Pollis_ready()or use an external notification.- There is no
set_exception()and no broken promise notification. A consumer cannot distinguish a slow producer from one that has gone away.
Availability
The header requires etl::atomic_bool. The classes are only defined when ETL_HAS_ATOMIC is 1
(see etl::atomic).
Thread safety
set_value() and is_ready()/get() may be called from different threads or contexts, provided that at most
one context calls set_value() and at most one context calls get(). The ready flag uses
release/acquire ordering, so a value written by set_value() is visible after is_ready() returns true.
reset() must not be called concurrently with any other member.
shared_state
Holds the result and an atomic ready flag. Non-copyable.
shared_state()
Description
Constructs a state that is not ready.
~shared_state()
Description
Destroys the stored value, if one has been set.
void set_value(const T& value)
void set_value(T&& value) // C++11
void set_value(T& value) // shared_state<T&> only
void set_value() // shared_state<void> only
Description
Stores the value (or, for shared_state<T&>, the address of the referenced object) and marks the state as ready.
Asserts etl::promise_already_satisfied if the state is already ready. Call reset() first to reuse the state.
bool is_ready() const noexcept
Description
Returns true if a value has been set.
T& get()
const T& get() const
T& get() const // shared_state<T&> only
Description
Returns a reference to the stored value.
Not available for shared_state<void>.
Asserts etl::future_not_ready if the state is not ready.
void reset()
Description
Destroys the stored value, if any, and marks the state as not ready, so that it can be reused.
future
A non-owning handle to a shared_state. Copyable, with the semantics of std::shared_future.
future() noexcept
Description
Constructs a future that is not associated with a shared state. valid() returns false.
explicit future(etl::shared_state<T>& state) noexcept
Description
Constructs a future associated with state.
bool valid() const noexcept
Description
Returns true if the future is associated with a shared state.
bool is_ready() const noexcept
Description
Returns true if the future is valid and the result is available.
const T& get() const
R& get() const // future<R&> only
void get() const // future<void> only
Description
Returns the result.
Asserts etl::future_no_state if the future is not valid (default constructed, no shared state).
Asserts etl::future_not_ready if the future is valid but the result is not yet available.
Does not block. Poll is_ready() or use an external notification first.
The value is not moved out and the future remains valid, so get() may be called more than once.
promise
A non-owning handle to a shared_state that fulfils it. Move-only (C++11) or non-copyable (C++03), so that there is
only one producer.
promise() noexcept
Description
Constructs a promise that is not associated with a shared state. valid() returns false.
explicit promise(etl::shared_state<T>& state) noexcept
Description
Constructs a promise associated with state.
promise(promise&& other) noexcept // C++11
promise& operator=(promise&& other) noexcept // C++11
Description
Transfers the association with the shared state. other is no longer valid.
bool valid() const noexcept
Description
Returns true if the promise is associated with a shared state.
etl::future<T> get_future()
Description
Returns a future associated with the same shared state.
May be called more than once. All futures refer to the same state.
Asserts etl::future_no_state if the promise is not valid.
void set_value(const T& value)
void set_value(T&& value) // C++11
void set_value(R& value) // promise<R&> only
void set_value() // promise<void> only
Description
Fulfils the promise.
Asserts etl::future_no_state if the promise is not valid.
Asserts etl::promise_already_satisfied if the shared state is already ready.
Errors
| Exception | Reason | Error text |
|---|---|---|
etl::future_exception |
Base of all future/promise exceptions. | |
etl::future_not_ready |
get() on a future or state that is not ready. |
future:not ready |
etl::promise_already_satisfied |
set_value() on a state that is already ready. |
promise:already satisfied |
etl::future_no_state |
Use of a future or promise that has no shared state. |
future:no state |
etl::future_exception is derived from etl::exception.
Example
#include "etl/future.h"
etl::shared_state<int> state; // Owned by the application.
// Consumer
etl::promise<int> promise(state);
etl::future<int> future = promise.get_future();
// Producer (e.g. in an ISR or another thread)
promise.set_value(42);
// Consumer
if (future.is_ready())
{
int result = future.get(); // 42
}
// Reuse the state for the next request.
state.reset();