Base module

provides classes and functions to create continuable_base objects.

Contents

Classes

template<typename Data, typename Annotation>
class cti::continuable_base
The main class of the continuable library, it provides the functionality for chaining callbacks and continuations together to a unified hierarchy.
template<typename Data, typename Hint>
class cti::promise_base
The promise_base makes it possible to resolve an asynchronous continuable through it's result or through an error type.

Typedefs

template<typename T>
using is_continuable = detail::base::is_continuable<T>
Deduces to a true_type if the given type is a continuable_base.

Functions

template<typename... Args, typename Continuation>
auto make_continuable(Continuation&& continuation) -> auto constexpr
Creates a continuable_base from a promise/callback taking function.
template<typename... Args>
auto make_ready_continuable(Args && ... args) -> auto
Returns a continuable_base with no result which instantly resolves the promise with no values.
template<typename... Args, typename Exception>
auto make_exceptional_continuable(Exception&& exception) -> auto constexpr
Returns a continuable_base with the parameterized result which instantly resolves the promise with the given error type.
template<typename... Signature>
auto make_cancelling_continuable() -> auto
Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.
template<typename T>
auto make_plain(T&& value) -> auto
Can be used to disable the special meaning for a returned value in asynchronous handler functions.
template<typename... Args>
auto recover(Args && ... args) -> result<detail::traits::unrefcv_t<Args>...>
Can be used to recover to from a failure handler, the result handler which comes after will be called with the corresponding result.
auto rethrow(exception_t exception) -> exceptional_result
Can be used to rethrow an exception to the asynchronous continuation chain, the failure handler which comes after will be called with the corresponding exception.
auto cancel() -> cancellation_result
Can be used to cancel an asynchronous continuation chain, the next failure handler which comes after cancel will be called with a default constructed exception_t object.
auto stop() -> empty_result
Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.

Typedef documentation

template<typename T>
using is_continuable = detail::base::is_continuable<T>

Deduces to a true_type if the given type is a continuable_base.

Function documentation

template<typename... Args, typename Continuation>
auto make_continuable(Continuation&& continuation) constexpr

Creates a continuable_base from a promise/callback taking function.

Template parameters
Args

The types (signature hint) the given promise is resolved with.

  • Some arguments indicate the types the promise will be invoked with.

    auto ct = cti::make_continuable<int, std::string>([](auto&& promise) {
      promise.set_value(200, "<html>...</html>");
    });
  • void as argument indicates that the promise will be invoked with no arguments:

    auto ct = cti::make_continuable<void>([](auto&& promise) {
      promise.set_value();
    });
  • No arguments Since version 3.0.0 make_continuable always requires to be given valid arguments! You should always give the type hint a callback is called with because it's required for intermediate actions like connecting continuables. You may omit the signature hint if you are erasing the type of the continuable right after creation.

    // This won't work because the arguments are missing:
    auto ct = cti::make_continuable([](auto&& promise) {
      promise.set_value(0.f, 'c');
    });
    
    // However, you are allowed to do this:
    cti::continuable<float, char> ct = [](auto&& promise) {
      promise.set_value(callback)(0.f, 'c');
    };
Continuation
Parameters
continuation

The continuation the continuable is created from. The continuation must be a callable type accepting a callback parameter which represents the object invokable with the asynchronous result of this continuable.

auto ct = cti::make_continuable<std::string>([](auto&& promise) {
  promise.set_value("result");
});

The callback may be stored or moved. In some cases the callback may be copied if supported by the underlying callback chain, in order to invoke the call chain multiple times. It's recommended to accept any callback instead of erasing it.

// Good practice:
auto ct = cti::make_continuable<std::string>([](auto&& promise) {
  promise.set_value("result");
});

// Good practice using a callable object:
struct Continuation {
  template<typename T>
  void operator() (T&& continuation) && {
    // ...
  }
}

auto ct = cti::make_continuable<std::string>(Continuation{});

// Bad practice (because of unnecessary type erasure):
auto ct = cti::make_continuable<std::string>(
  [](cti::promise<std::string> promise) {
    promise.set_value("result");
  });
Returns A continuable_base with unspecified template parameters which wraps the given continuation. In order to convert the continuable_base to a known type you need to apply type erasure through the continuable or promise facilities.

template<typename... Args>
auto make_ready_continuable(Args && ... args)

Returns a continuable_base with no result which instantly resolves the promise with no values.

template<typename... Args, typename Exception>
auto make_exceptional_continuable(Exception&& exception) constexpr

Returns a continuable_base with the parameterized result which instantly resolves the promise with the given error type.

Template parameters
Args The fake signature of the returned continuable.
Exception

See an example below:

std::logic_error exception("Some issue!");
auto ptr = std::make_exception_ptr(exception);
auto ct = cti::make_exceptional_continuable<int>(ptr);

template<typename... Signature>
auto make_cancelling_continuable()

Returns a continuable_base with the parameterized result which never resolves its promise and thus cancels the asynchronous continuation chain through throwing a default constructed exception_t.

Template parameters
Signature The fake signature of the returned continuable.

This can be used to cancel an asynchronous continuation chain when returning a continuable_base from a handler where other paths could possibly continue the asynchronous chain. See an example below:

do_sth().then([weak = this->weak_from_this()]() -> continuable<> {
  if (auto me = weak.lock()) {
    return do_sth_more();
  } else {
    // Abort the asynchronous continuation chain since the
    // weakly referenced object expired previously.
    return make_cancelling_continuable<void>();
  }
});

The default unhandled exception handler ignores exception types that don't evaluate to true when being converted to a bool. This saves expensive construction of std::exception_ptr or similar types, where only one exception type is used for signaling the cancellation.

template<typename T>
auto make_plain(T&& value)

Can be used to disable the special meaning for a returned value in asynchronous handler functions.

Several types have a special meaning when being returned from a callable passed to asynchronous handler functions like:

For instance such types are std::tuple, std::pair and cti::result.

Wrapping such an object through a call to make_plain disables the special meaning for such objects as shown below:

continuable<result<int, int> c = http_request("example.com")
  .then([](std::string content) {
    return make_plain(make_result(0, 1));
  })

template<typename... Args>
result<detail::traits::unrefcv_t<Args>...> recover(Args && ... args)

Can be used to recover to from a failure handler, the result handler which comes after will be called with the corresponding result.

The exceptional_result returned by this function can be returned from any result or failure handler in order to rethrow the exception.

http_request("example.com")
  .then([](std::string content) {
    return recover(1, 2);
  })
  .fail([](cti::exception_t exception) {
    return recover(1, 2);
  })
  .then([](int a, int b) {
    // Recovered from the failure
  })

A corresponding result is returned by recover

http_request("example.com")
  .then([](std::string content) -> cti::result<int, int> {
    return recover(1, 2);
  })
  .fail([](cti::exception_t exception) -> cti::result<int, int> {
    return recover(1, 2);
  })
  .then([](int a, int b) -> cti::result<int, int> {
    // Recovered from the failure
  })

exceptional_result rethrow(exception_t exception)

Can be used to rethrow an exception to the asynchronous continuation chain, the failure handler which comes after will be called with the corresponding exception.

The exceptional_result returned by this function can be returned from any result or failure handler in order to rethrow the exception.

http_request("example.com")
  .then([](std::string content) {
    return rethrow(std::make_exception_ptr(std::exception{}));
  })
  .fail([](cti::exception_t exception) {
    return rethrow(std::make_exception_ptr(std::exception{}));
  })
  .next([](auto&&...) {
    return rethrow(std::make_exception_ptr(std::exception{}));
  });

The returned exceptional_result is convertible to any result as shown below:

http_request("example.com")
  .then([](std::string content) -> cti::result<> {
    return rethrow(std::make_exception_ptr(std::exception{}));
  })
  .fail([](cti::exception_t exception) -> cti::result<> {
    return rethrow(std::make_exception_ptr(std::exception{}));
  })
  .next([](auto&&...) -> cti::result<> {
    return rethrow(std::make_exception_ptr(std::exception{}));
  });

cancellation_result cancel()

Can be used to cancel an asynchronous continuation chain, the next failure handler which comes after cancel will be called with a default constructed exception_t object.

The cancellation_result returned by this function can be returned from any result or failure handler in order to cancel the chain.

http_request("example.com")
  .then([](std::string content) {
    return cancel();
  })
  .fail([](cti::exception_t exception) {
    return cancel();
  })
  .next([](auto&&...) {
    return cancel();
  });

The returned empty_result is convertible to any result as shown below:

http_request("example.com")
  .then([](std::string content) -> cti::result<> {
    return cancel();
  })
  .fail([](cti::exception_t exception) -> cti::result<> {
    return cancel();
  })
  .next([](auto&&...) -> cti::result<> {
    return cancel();
  });

empty_result stop()

Can be used to stop an asynchronous continuation chain, no handler which comes after stop was received won't be called.