template class EE::Task¶
Overview¶
The result of an operation that completes later. More…
#include <task.hpp> template <typename T> class Task { public: // typedefs typedef T ValueType; // construction Task(); Task(Task&&); Task(const Task&); // methods Task& operator=(Task&&); Task& operator=(const Task&); bool valid() const; TaskState state() const; bool isReady() const; bool isPending() const; TaskState wait() const; template <typename Rep, typename Period> TaskState waitFor(const std::chrono::duration<Rep, Period>& timeout) const; T takeValue(); auto get(); template <typename F> auto then(Executor& executor, F&& fn); template <typename F> auto then(F&& fn); template <typename F> void onComplete(F&& fn); static Task create(TaskResolver<T>& resolve); template <typename... Args> static Task ready(Args&&... args); };
Detailed Documentation¶
The result of an operation that completes later.
The consumer’s end. The producer completes it through the TaskResolver that create() fills in. Task is move-only and carries no domain error semantics: fallible operations return Task <Result<T, E>>. Attaching a continuation consumes the task (std::move( task ).then( ... )), so only one continuation chain can ever exist.
then( executor, fn ): runs fn through the executor (for example the UI thread’s), even if the task has already completed. This is the normal way to use a result.
then( fn ): runs fn on whichever thread completes the task, or right away on the calling thread if it already has. For cheap transformations that touch no thread-bound state.
fn may return a value, void, or a Task; nested tasks are flattened into Task.
If the task is abandoned, fn is not called and the returned task is abandoned too.
onComplete( fn ) also observes abandonment: fn receives std::nullopt.
Construction¶
Task()
Creates an invalid task. Its state() is Abandoned.
Methods¶
TaskState wait() const
Blocks until the task is Ready or Abandoned.
This is a low-level bridge for worker-thread adapters and tests. It must never be called on the UI thread, nor on the thread that is expected to resolve the task.
template <typename Rep, typename Period> TaskState waitFor(const std::chrono::duration<Rep, Period>& timeout) const
Blocks until the task completes or the timeout expires.
Returns:
The state on return.
T takeValue()
Extracts the value of a Ready task and consumes it. Precondition: isReady().
auto get()
Blocks until completion and returns the value, or std::nullopt if abandoned. Same threading restrictions as wait().
template <typename F> auto then(Executor& executor, F&& fn)
Runs fn( value ) through executor once the task completes, even if it already has. The executor must outlive the task chain. See the class documentation.
template <typename F> auto then(F&& fn)
Runs fn( value ) on the thread that completes the task, or right away on the calling thread if it already has. See the class documentation.
template <typename F> void onComplete(F&& fn)
Observes the outcome without producing a new task, on the thread that completes the task (or right away on the calling thread if it already has). fn( std::optional<T> value ) receives the value, or std::nullopt if the task was abandoned; for Task<void>, fn( bool completed ) receives false if it was abandoned.
static Task create(TaskResolver<T>& resolve)
TaskResolver<int> resolve; auto task = Task<int>::create( resolve ); pool.execute( [resolve] { resolve( 42 ); } ); return task;
Returns:
A pending task. resolve is set to the resolver that completes it (a resolver it held before is released).
template <typename... Args> static Task ready(Args&&... args)
Returns:
A task that is already Ready with the given value.