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

@ -33,6 +33,7 @@ in order to change the libraries behaviour:
| `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_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_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. | | `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 /// \since 1.0.0
void done() && { void done() && {
detail::base::finalize_continuation(std::move(*this)); detail::base::finalize_continuation(std::move(*this).finish());
} }
/// Materializes the continuation expression template and finishes /// 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)}; std::forward<NextCallback>(next_callback)};
} }
// TODO fixate the args /// Represents the last callback in the asynchronous continuation chain
/// Once this was a workaround for GCC bug: template <typename... Args>
/// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095
struct final_callback : util::non_copyable { struct final_callback : util::non_copyable {
template <typename... Args>
void operator()(Args... /*args*/) && { void operator()(Args... /*args*/) && {
} }
@ -670,7 +668,6 @@ struct final_callback : util::non_copyable {
#endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS #endif // CONTINUABLE_WITH_UNHANDLED_EXCEPTIONS
} }
template <typename... Args>
void set_value(Args... args) { void set_value(Args... args) {
std::move (*this)(std::forward<Args>(args)...); std::move (*this)(std::forward<Args>(args)...);
} }
@ -876,10 +873,16 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback,
/// ///
/// For example given: /// For example given:
/// - Continuation: continuation<[](auto&& callback) { callback("hi"); }> /// - Continuation: continuation<[](auto&& callback) { callback("hi"); }>
template <typename Continuation> template <typename Data, typename... Args>
void finalize_continuation(Continuation&& continuation) { void finalize_continuation(
invoke_continuation(std::forward<Continuation>(continuation), continuable_base<Data, traits::identity<Args...>>&& continuation) noexcept {
callbacks::final_callback{}); #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 /// 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> template <typename Data, typename... Args, typename Continuation>
struct can_accept_continuation<Data, traits::identity<Args...>, Continuation> struct can_accept_continuation<Data, traits::identity<Args...>, Continuation>
: traits::conjunction< : traits::conjunction<
traits::is_invocable<Continuation, callbacks::final_callback>, traits::is_invocable<Continuation,
callbacks::final_callback<Args...>>,
std::is_convertible< std::is_convertible<
proxy_continuable<traits::identity<Args...>, Continuation>, proxy_continuable<traits::identity<Args...>, Continuation>,
Data>> {}; Data>> {};