Fixate the args of the final callback

* Also allow to customize it through the
  CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK define.
  This can be used to implement custom unhandled
  exception handlers and more.
This commit is contained in:
Denis Blank 2018-12-29 06:11:03 +01:00
parent a099c504e1
commit 3bd4dd40de
3 changed files with 17 additions and 12 deletions

View File

@ -30,9 +30,10 @@ in order to change the libraries behaviour:
| Preprocessor definition | Consequence |
| ----------------------------------------- | --------------- |
| `CONTINUABLE_WITH_NO_EXCEPTIONS` | Exceptions are disabled and `std::error_condition` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
| `CONTINUABLE_WITH_NO_EXCEPTIONS` | Exceptions are disabled and `std::error_condition` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
| `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` | Exceptions are disabled and the type defined by `CONTINUABLE_WITH_CUSTOM_ERROR_TYPE` is used as \ref error_type . See \ref tutorial-chaining-continuables-fail for details. |
| `CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS` | Allows unhandled exceptions in asynchronous call hierarchies. See \ref tutorial-chaining-continuables-fail for details. |
| `CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK` | Allows to customize the final callback which can be used to implement custom unhandled asynchronous exception handlers. |
| `CONTINUABLE_WITH_EXPERIMENTAL_COROUTINE` | Enables support for experimental coroutines and `co_await` expressions. See \ref continuable_base::operator co_await() for details. |
*/

View File

@ -582,7 +582,7 @@ public:
///
/// \since 1.0.0
void done() && {
detail::base::finalize_continuation(std::move(*this));
detail::base::finalize_continuation(std::move(*this).finish());
}
/// Materializes the continuation expression template and finishes

View File

@ -641,11 +641,9 @@ auto make_callback(Callback&& callback, Executor&& executor,
std::forward<NextCallback>(next_callback)};
}
// TODO fixate the args
/// Once this was a workaround for GCC bug:
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
/// Represents the last callback in the asynchronous continuation chain
template <typename... Args>
struct final_callback : util::non_copyable {
template <typename... Args>
void operator()(Args... /*args*/) && {
}
@ -670,7 +668,6 @@ struct final_callback : util::non_copyable {
#endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
}
template <typename... Args>
void set_value(Args... args) {
std::move (*this)(std::forward<Args>(args)...);
}
@ -876,10 +873,16 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
///
/// For example given:
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
template <typename Continuation>
void finalize_continuation(Continuation&& continuation) {
invoke_continuation(std::forward<Continuation>(continuation),
callbacks::final_callback{});
template <typename Data, typename... Args>
void finalize_continuation(
continuable_base<Data, traits::identity<Args...>>&& continuation) noexcept {
#ifdef CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
invoke_continuation(std::move(continuation),
CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK<Args...>{});
#else // CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
invoke_continuation(std::move(continuation),
callbacks::final_callback<Args...>{});
#endif // CONTINUABLE_WITH_CUSTOM_FINAL_CALLBACK
}
/// Deduces to a true type if the given callable data can be wrapped
@ -889,7 +892,8 @@ struct can_accept_continuation : std::false_type {};
template <typename Data, typename... Args, typename Continuation>
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
: traits::conjunction<
traits::is_invocable<Continuation, callbacks::final_callback>,
traits::is_invocable<Continuation,
callbacks::final_callback<Args...>>,
std::is_convertible<
proxy_continuable<traits::identity<Args...>, Continuation>,
Data>> {};