template<typename Data, typename Annotation>
continuable_base class
The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.
Template parameters | |
---|---|
Data | The internal data which is used to store the current continuation and intermediate lazy connection result. |
Annotation | The internal data used to store the current signature hint or strategy used for combining lazy connections. |
Contents
The most important method is the cti::
Use the continuable types defined in continuable/
, in order to use this class.
Constructors, destructors, conversion operators
- continuable_base(Data data) explicit
- Constructor accepting the data object while erasing the annotation.
-
template<typename OtherData, std::enable_if_t<detail::base::can_accept_continuation<Data, Annotation, detail::traits::unrefcv_t<OtherData>>::value>* = nullptr>continuable_base(OtherData&& data)
- Constructor accepting any object convertible to the data object, while erasing the annotation.
-
template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>continuable_base(continuable_
base<OData, Annotation>&& other) - Constructor taking the data of other continuable_
base objects while erasing the hint. -
template<typename OData, typename OAnnotation>continuable_base(continuable_
base<OData, OAnnotation>&& other) - Constructor taking the data of other continuable_
base objects while erasing the hint. - ~continuable_base()
- The destructor automatically invokes the continuable_
base if it wasn't consumed yet.
Public functions
-
template<typename T, typename E = detail::types::this_thread_executor_tag>auto then(T&& callback, E&& executor = detail::types::this_thread_executor_tag{}) && -> auto
- Main method of the continuable_
base to chain the current continuation with a new callback. -
template<typename OData, typename OAnnotation>auto then(continuable_
base<OData, OAnnotation>&& continuation) && -> auto - Additional overload of the continuable_base::
then() method which is accepting a continuable_ base itself. -
template<typename T, typename E = detail::types::this_thread_executor_tag>auto fail(T&& callback, E&& executor = detail::types::this_thread_executor_tag{}) && -> auto
- Main method of the continuable_
base to catch exceptions and error codes in case the asynchronous control flow failed and was resolved through an error code or exception. -
template<typename OData, typename OAnnotation>auto fail(continuable_
base<OData, OAnnotation>&& continuation) && -> auto - Additional overload of the continuable_base::
fail() method which is accepting a continuable_ base itself. -
template<typename T, typename E = detail::types::this_thread_executor_tag>auto next(T&& callback, E&& executor = detail::types::this_thread_executor_tag{}) && -> auto
- A method which allows to use an overloaded callable for the error as well as the valid result path.
-
template<typename... Args>auto as() && -> auto
- Returns a continuable_
base which will have its signature converted to the given Args. -
template<typename T>auto apply(T&& transform) && -> auto
- A method which allows to apply a callable object to this continuable.
-
template<typename T>auto operator|(T&& right) && -> auto
- The pipe operator | is an alias for the continuable::
then method. -
template<typename OData, typename OAnnotation>auto operator&&(continuable_
base<OData, OAnnotation>&& right) && -> auto - Invokes both continuable_
base objects parallel and calls the callback with the result of both continuable_ base objects. -
template<typename OData, typename OAnnotation>auto operator||(continuable_
base<OData, OAnnotation>&& right) && -> auto - Invokes both continuable_
base objects parallel and calls the callback once with the first result available. -
template<typename OData, typename OAnnotation>auto operator>>(continuable_
base<OData, OAnnotation>&& right) && -> auto - Invokes both continuable_
base objects sequential and calls the callback with the result of both continuable_ base objects. - void done() &&
- Invokes the continuation chain manually even before the cti::
continuable_base is destructed. This will release the object. - auto finish() && -> auto
- Materializes the continuation expression template and finishes the current applied strategy such that the resulting continuable will always be a concrete type and Continuable::is_concrete holds.
- auto is_ready() const -> bool noexcept
- Returns true when the continuable can provide its result immediately, and its lazy invocation would be side-effect free.
- auto unpack() && -> auto
- Invalidates the continuable and returns its immediate invocation result.
- auto is_frozen() const -> bool noexcept
- Predicate to check whether the cti::
continuable_base is frozen or not. -
auto freeze(bool enabled = true) &noexcept -> continuable_
base& - Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_
base. You may still invoke the chain through the continuable_base:: done method. -
auto freeze(bool enabled = true) &&noexcept -> continuable_
base&& - Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_
base. You may still invoke the chain through the continuable_base:: done method. - auto operator co_await() && -> auto
- Implements the operator for awaiting on continuables using
co_await
.
Function documentation
template<typename Data, typename Annotation>
template<typename OData, std::enable_if_t<std::is_convertible<detail::traits::unrefcv_t<OData>, Data>::value>* = nullptr>
cti:: continuable_base<Data, Annotation>:: continuable_base(continuable_ base<OData, Annotation>&& other)
Constructor taking the data of other continuable_
This constructor makes it possible to replace the internal data object of the continuable by any object which is useful for type-erasure.
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
cti:: continuable_base<Data, Annotation>:: continuable_base(continuable_ base<OData, OAnnotation>&& other)
Constructor taking the data of other continuable_
This constructor makes it possible to replace the internal data object of the continuable by any object which is useful for type-erasure.
template<typename Data, typename Annotation>
cti:: continuable_base<Data, Annotation>:: ~continuable_base()
The destructor automatically invokes the continuable_
In order to invoke the continuable early you may call the continuable_base::
The continuable_base::
template<typename Data, typename Annotation>
template<typename T, typename E = detail::types::this_thread_executor_tag>
auto cti:: continuable_base<Data, Annotation>:: then(T&& callback,
E&& executor = detail::types::this_thread_executor_tag{}) &&
Main method of the continuable_
Parameters | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
callback | The callback which is used to process the current asynchronous result on arrival. The callback is required to accept the current result at least partially (or nothing of the result). (http_request("github.com") && http_request("atom.io")) .then([](std::string github, std::string atom) { // We use the whole result }); (http_request("github.com") && http_request("atom.io")) .then([](std::string github) { // We only use the result partially }); (http_request("github.com") && http_request("atom.io")) .then([] { // We discard the result }); |
||||||||||||||
executor | The optional executor which is used to dispatch the callback. The executor needs to accept callable objects callable through an auto executor = [](auto&& work) { // Dispatch the work here or forward it to an executor of // your choice. std::forward<decltype(work)>(work)(); }; http_request("github.com") .then([](std::string github) { // Do something... }, executor); |
||||||||||||||
Returns | Returns a continuable_
Which means the result type of the continuable_ http_request("github.com") .then([](std::string github) { return; }) .then([] { }); // <void> http_request("github.com") .then([](std::string github) { return 0; }) .then([](int a) { }); // <int> http_request("github.com") .then([](std::string github) { return std::make_pair(1, 2); }) .then([](int a, int b) { }); // <int, int> http_request("github.com") .then([](std::string github) { return std::make_tuple(1, 2, 3); }) .then([](int a, int b, int c) { }); // <int, int, int> http_request("github.com") .then([](std::string github) { return http_request("atom.io"); }) .then([](std::string atom) { }); // <std::string> http_request("example.com") .then([](std::string content) -> result<std::string> { return rethrow(std::make_exception_ptr(std::exception{})); }) .fail([] -> result<std::string> { return recover("Hello World!"); }) .then([](std::string content) -> result<std::string> { return cancel(); }) |
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
auto cti:: continuable_base<Data, Annotation>:: then(continuable_ base<OData, OAnnotation>&& continuation) &&
Additional overload of the continuable_base::
Parameters | |
---|---|
continuation | A continuable_ http_request("github.com") .then(http_request("atom.io")) .then([](std::string atom) { // ... }); |
Returns | Returns a continuable_ |
template<typename Data, typename Annotation>
template<typename T, typename E = detail::types::this_thread_executor_tag>
auto cti:: continuable_base<Data, Annotation>:: fail(T&& callback,
E&& executor = detail::types::this_thread_executor_tag{}) &&
Main method of the continuable_
Parameters | |
---|---|
callback | The callback which is used to process the current asynchronous error result on arrival. In case the continuable_ |
executor | The optional executor which is used to dispatch the callback. See the description in then above. |
Returns | Returns a continuable_ |
http_request("github.com") .then([](std::string github) { }) .fail([](std::exception_ptr ep) { // Check whether the exception_ptr is valid (not default constructed) // if bool(ep) == false this means that the operation was cancelled // by the user or application (promise.set_canceled() or // make_cancelling_continuable()). if (ep) { // Handle the error here try { std::rethrow_exception(ep); } catch (std::exception& e) { e.what(); // Handle the exception } } });
In case exceptions are disabled, std::error_condition
is used as error result instead of std::exception_ptr
.
http_request("github.com") .then([](std::string github) { }) .fail([](std::error_condition error) { error.message(); // Handle the error here });
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
auto cti:: continuable_base<Data, Annotation>:: fail(continuable_ base<OData, OAnnotation>&& continuation) &&
Additional overload of the continuable_base::
Parameters | |
---|---|
continuation | A continuable_ http_request("github.com") .fail(http_request("atom.io")) |
Returns | Returns a continuable_ |
template<typename Data, typename Annotation>
template<typename T, typename E = detail::types::this_thread_executor_tag>
auto cti:: continuable_base<Data, Annotation>:: next(T&& callback,
E&& executor = detail::types::this_thread_executor_tag{}) &&
A method which allows to use an overloaded callable for the error as well as the valid result path.
Parameters | |
---|---|
callback | The callback which is used to process the current asynchronous result and error on arrival. |
executor | The optional executor which is used to dispatch the callback. See the description in then above. |
Returns | Returns a continuable_ |
struct my_callable { void operator() (std::string result) { // ... } void operator() (cti::exception_arg_t, cti::exception_t) { // ... } // Will receive errors and results http_request("github.com") .next(my_callable{});
template<typename Data, typename Annotation>
template<typename... Args>
auto cti:: continuable_base<Data, Annotation>:: as() &&
Returns a continuable_
Returns | Returns a continuable_ |
---|
A signature can only be converted if it can be partially applied from the previous one as shown below: continuable<long> c = make_ready_continuable(0, 1, 2).as<long>();
template<typename Data, typename Annotation>
template<typename T>
auto cti:: continuable_base<Data, Annotation>:: apply(T&& transform) &&
A method which allows to apply a callable object to this continuable.
Parameters | |
---|---|
transform | A callable objects that transforms a continuable to a different object. |
Returns | Returns the result of the given transform when this continuable is passed into it. |
template<typename Data, typename Annotation>
template<typename T>
auto cti:: continuable_base<Data, Annotation>:: operator|(T&& right) &&
The pipe operator | is an alias for the continuable::
Parameters | |
---|---|
right | The argument on the right-hand side to connect. |
Returns | See the corresponding continuable_base:: |
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
auto cti:: continuable_base<Data, Annotation>:: operator&&(continuable_ base<OData, OAnnotation>&& right) &&
Invokes both continuable_
Parameters | |
---|---|
right | The continuable on the right-hand side to connect. |
Returns | Returns a continuable_ (http_request("github.com") && http_request("atom.io")) .then([](std::string github, std::string atom) { // ... }); auto request = http_request("github.com") && http_request("atom.io"); (std::move(request) && http_request("travis-ci.org")) // All three requests are invoked in parallel although we added // the request to "travis-ci.org" last. .then([](std::string github, std::string atom, std::string travis) { // ... }); |
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
auto cti:: continuable_base<Data, Annotation>:: operator||(continuable_ base<OData, OAnnotation>&& right) &&
Invokes both continuable_
Parameters | |
---|---|
right | The continuable on the right-hand side to connect. The right continuable is required to have the same result as the left connected continuable_ |
Returns | Returns a continuable_ (http_request("github.com") || http_request("atom.io")) .then([](std::string github_or_atom) { // ... }); (make_ready_continuable(10, 'A') || make_ready_continuable(29, 'B')) .then([](int a, char b) { // ... }); |
template<typename Data, typename Annotation>
template<typename OData, typename OAnnotation>
auto cti:: continuable_base<Data, Annotation>:: operator>>(continuable_ base<OData, OAnnotation>&& right) &&
Invokes both continuable_
Parameters | |
---|---|
right | The continuable on the right-hand side to connect. |
Returns | Returns a continuable_ (http_request("github.com") >> http_request("atom.io")) .then([](std::string github, std::string atom) { // The callback is called with the result of both requests, // however, the request to atom was started after the request // to github was finished. }); |
template<typename Data, typename Annotation>
void cti:: continuable_base<Data, Annotation>:: done() &&
Invokes the continuation chain manually even before the cti::
template<typename Data, typename Annotation>
auto cti:: continuable_base<Data, Annotation>:: finish() &&
Materializes the continuation expression template and finishes the current applied strategy such that the resulting continuable will always be a concrete type and Continuable::is_concrete holds.
This can be used in the case where we are chaining continuations lazily through a strategy, for instance when applying operators for expressing connections and then want to return a materialized continuable_
auto do_both() { return (wait(10s) || wait_key_pressed(KEY_SPACE)).finish(); } // Without a call to finish() this would lead to // an unintended evaluation strategy: do_both() || wait(5s);
template<typename Data, typename Annotation>
bool cti:: continuable_base<Data, Annotation>:: is_ready() const noexcept
Returns true when the continuable can provide its result immediately, and its lazy invocation would be side-effect free.
template<typename Data, typename Annotation>
auto cti:: continuable_base<Data, Annotation>:: unpack() &&
Invalidates the continuable and returns its immediate invocation result.
Returns | A result<Args...> where Args... represent the current asynchronous parameters or the currently stored exception. |
---|
This method can be used to specialize the asynchronous control flow based on whether the continuable_
- make_ready_continuable
- make_exceptional_continuable
template<typename Data, typename Annotation>
bool cti:: continuable_base<Data, Annotation>:: is_frozen() const noexcept
Predicate to check whether the cti::
Returns | Returns true when the continuable_ |
---|
template<typename Data, typename Annotation>
continuable_ base& cti:: continuable_base<Data, Annotation>:: freeze(bool enabled = true) &noexcept
Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_
Parameters | |
---|---|
enabled | Indicates whether the freeze is enabled or disabled. |
This is useful for storing a continuable_
template<typename Data, typename Annotation>
continuable_ base&& cti:: continuable_base<Data, Annotation>:: freeze(bool enabled = true) &&noexcept
Prevents the automatic invocation of the continuation chain which happens on destruction of the continuable_
Parameters | |
---|---|
enabled | Indicates whether the freeze is enabled or disabled. |
This is useful for storing a continuable_
template<typename Data, typename Annotation>
auto cti:: continuable_base<Data, Annotation>:: operator co_await() &&
Implements the operator for awaiting on continuables using co_await
.
The operator is only enabled if CONTINUABLE_HAS_EXPERIMENTAL_COROUTINE
is defined and the toolchain supports experimental coroutines.
The return type of the co_await
expression is specified as following:
Continuation type | co_await returns |
---|---|
continuable_ | void |
continuable_ | Arg |
continuable_ | std::tuple<Args...> |
When exceptions are used the usage is as intuitive as shown below:
// Handling the exception isn't required and // the try catch clause may be omitted. try { std::string response = co_await http_request("github.com"); } (std::exception& e) { e.what(); }
In case the library is configured to use error codes or a custom exception type the return type of the co_await expression is changed. The result is returned through a cti::result<...>.
Continuation type | co_await returns |
---|---|
continuable_ | result<void> |
continuable_ | result<Arg> |
continuable_ | result<Args...> |