early_termination_task
provides facitilies to terminate a coroutine
before its normal termination, potentially returning a value indicating
this termination.
C++ dialects aim to make exception throwing and catching as inexpensive
as possible, but few implementations are able to achieve the efficiency
of ordinary return value semantics. This, unfortunately, often leads to
code and runtime inefficiency of successful execution, due to the
need to write if (error) { return; }
statements after every operation
that could fail. This litters the code with such checks, and adds additional
conditional branch instructions to the instruction stream.
early_termination_task
provides a framework for eliminating these
efficiencies by providing these features:
- The ability to
co_await
an arbitrary type to check that it contains an error. - The ability to
co_await
anearly_termination_task
that itself is parameterized on an error type. - Upon detection of an error, resuming the inner most error handler for that error.
- The ability to
co_await
anearly_termination_task
and specify that the wait operation is an error handler, thus being a valid target for #3. - The ability to handle thrown exceptions by translating them in the same way.
- The ability to translate errors and exceptions into an appropriate result of callers of an
early_termination_task
.
These mechanisms imply that the co_await
expressions in such a coroutine
may suspend a coroutine and resume a calling coroutine without throwing an exception;
the resumption of the caller will typically result in the destruction of the coroutine
so suspended. This means that try / catch error handling will not work, and RAII based
releasing of resources is to be used at all times.
The types of ordinary results, of errors to handle,
and of the means to report errors are specified in the template parameters to
early_termination_task
.
early_termination_task
is built using the semantics of
task
. An early_termination_task
can only be awaited
once as an r-value and cannot be copied.
An example use would be:
template<
typename Value = void
>
using error_task = early_termination_task<
Value,
std::expected<
Value,
std::error_condition
>,
expected_early_termination_handler,
error_condition_early_termination_transformer
>;
error_task<int> MyErrorReturningCoroutine()
{
// This co_return will immediately cause the resumption of MyErrorHandlingCoroutine,
// without ever resuming code in MyOuterCoroutine.
co_return std::unexpected { std::make_error_condition(std::errc::bad_address) };
}
error_task<int> MySuccessfulCoroutine()
{
co_return 5;
}
error_task<int> MyOuterCoroutine()
{
return
// This co_await will succeed
co_await MySuccessfulCoroutine()
// This co_await will not return to this coroutine at all,
// with MyErrorReturningCoroutine immediately resuming MyErrorHandlingCoroutine.
+ co_await MyErrorReturningCoroutine();
}
error_task<int> MyErrorHandlingCoroutine()
{
auto result = co_await MyOuterCoroutine().handle_errors();
static_assert(
std::same<
std::expected<int, std::error_condition>,
decltype(result)>);
// If the error was bad_address,
// just return 0.
if (result == std::make_error_condition(std::errc::bad_address))
{
co_return 0;
}
// Otherwise, return the result value or the original error.
co_return co_await result;
}
The type arguments to early_termination_task
are:
- The type of the value returned by error-handling co_await operations.
- The policies and type handlers to apply to the
early_termination_task
.
For convenience, it is useful to user that handlers and reporters follow an implementation and naming convention matching that used by the library itself.
-
<error-type>_early_termination_transformer
Implements the behavior of determining that a given type should terminate a coroutine.
-
<error-type>_as_<result-type>_early_termination_result
Implements the behavior that a given type should be reported as a particular result value to error handlers.
-
_early_termination_result
Implements the behavior that all results should be reported as a particular result value to error handlers.
-
<error-type>_as_<result-type>_early_termination_result
Implements the behavior that a given type should be reported as a particular result value.
-
<error-type>_as_<result-type>_early_termination_handler
Combines the behavior of:
- <error-type>_early_termination_transformer
- <error-type>_as_<result-type>_early_termination_result
An early_termination_transformer
type derives from the class
early_termination_transformer
, and is expected to provide
an implementation of await_transform
that transforms
the handled result type with an ```early_termination_awaiter``-derived
awaiter.
An early_termination_result
type derives from the class
early_termination_result
, and is expected to provide
implementations of:
get_success_value(T&&)
retrieves a successful result from the full ErrorTypeget_error_value(T&&)
retrieves a full ErrorTypeis_error_value(T&&)
determines if a value returned from return_value is an error
An early_termination_handler
type simply derives
from both the early_termination_checker
and
early_termination_result
classes to provide compound behavior.
The default behavior for exception is as follows:
- An exception thrown by coroutine is caught by the
early_termination_promise
via itsunhandled_exception()
method. - The exception is "tunnelled" through all the non-handling
early_termination_task
tasks being awaited until either the top level task is reached or an error-handling await operation is encountered. - The exception is then rethrown into that coroutine.
This class acts as the base class for transformers that look at a particular error type.
This class is the base class for awaiters that handle a particular error type.
This class is the base class for transforming a result into a value returned to an error handling coroutine.
This file provides early_termination_task
behavior to handle
std::expected
instances. Any std::expected
whose
operator bool
returns false is considered to be an error
The classes provided are:
-
expected_early_termination_transformer
Performs
co_await
transformations to detect errors on anstd::expected
instance. -
expected_early_termination_result
Transforms errors into
std::expected
instance as necessary. -
expected_early_termination_handler
Combines the behavior of
expected_early_termination_result
andexpected_early_termination_transformer
.
This file provides early_termination_task
behavior to handle
std::error_condition
instances. Any std::error_condition
whose operator bool
returns true is considered to be an error.
The classes provided are:
-
error_condition_early_termination_transformer
Performs
co_await
transformations to detect errors on anstd::error_condition
instance.