From 6481b5454db57783f6a4e79a0127c90712f1e1f7 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Fri, 29 Sep 2017 15:38:41 +0200 Subject: [PATCH] Started on implementing error handler chaining * Namespace fixups --- include/continuable/continuable-base.hpp | 2 +- .../continuable/continuable-promise-base.hpp | 2 +- include/continuable/continuable-testing.hpp | 6 +- include/continuable/continuable.hpp | 4 +- include/continuable/detail/base.hpp | 78 ++++++++++++++++++- include/continuable/detail/composition.hpp | 6 +- include/continuable/detail/traits.hpp | 4 +- include/continuable/detail/util.hpp | 4 +- 8 files changed, 89 insertions(+), 17 deletions(-) diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 31c0b2f..47eb2f7 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -687,6 +687,6 @@ struct continuable_trait { continuable_base>; }; -} // end namespace cti +} // namespace cti #endif // CONTINUABLE_BASE_HPP_INCLUDED__ diff --git a/include/continuable/continuable-promise-base.hpp b/include/continuable/continuable-promise-base.hpp index af35a0d..f4c491a 100644 --- a/include/continuable/continuable-promise-base.hpp +++ b/include/continuable/continuable-promise-base.hpp @@ -82,6 +82,6 @@ public: data_(detail::base::dispatch_error_tag{}, std::move(error)); } }; -} // end namespace cti +} // namespace cti #endif // CONTINUABLE_PROMISE_BASE_HPP_INCLUDED__ diff --git a/include/continuable/continuable-testing.hpp b/include/continuable/continuable-testing.hpp index 7a22347..58bc1fb 100644 --- a/include/continuable/continuable-testing.hpp +++ b/include/continuable/continuable-testing.hpp @@ -120,9 +120,9 @@ void assert_async_types(C&& continuable, traits::identity expected) { "The called arguments don't match with the expected ones!"); }); } -} // end namespace testing -} // end namespace detail -} // end namespace cti +} // namespace testing +} // namespace detail +} // namespace cti /// Asserts that the final callback of the given continuable was called /// with any result. diff --git a/include/continuable/continuable.hpp b/include/continuable/continuable.hpp index 6db3552..0415ada 100644 --- a/include/continuable/continuable.hpp +++ b/include/continuable/continuable.hpp @@ -52,7 +52,7 @@ using unique_trait_of = continuable_trait< fu2::unique_function, Args... >; -} // end namespace detail +} // namespace detail /// Defines a copyable continuation type which uses the /// function2 backend for type erasure. @@ -94,6 +94,6 @@ using unique_callback = typename detail::unique_trait_of< // TODO sink // clang-format on -} // end namespace cti +} // namespace cti #endif // CONTINUABLE_HPP_INCLUDED__ diff --git a/include/continuable/detail/base.hpp b/include/continuable/detail/base.hpp index cfe96ec..ec3b68e 100644 --- a/include/continuable/detail/base.hpp +++ b/include/continuable/detail/base.hpp @@ -243,7 +243,7 @@ template constexpr auto invoker_of(traits::identity>) { return make_invoker(sequenced_unpack_invoker(), traits::identity{}); } -} // end namespace decoration +} // namespace decoration /// Invoke the callback immediately template +struct error_proxy; + +template +struct error_proxy, Callback, Executor, + NextCallback> { + Callback callback_; + Executor executor_; + NextCallback next_callback_; + + /// The operator which is called when the result was provided + void operator()(Args... args) { + // Forward the arguments to the next callback + std::move(next_callback_)(std::move(args)...); + } + + /// The operator which is called when an error occurred + void operator()(dispatch_error_tag /*tag*/, error_type error) { + // Forwárd the error to the error handler + // TODO + } +}; + +/// Chains an error handler together with a continuation and +/// returns a continuation. The current future result of the continuation +//// stays unchanged. +/// +template +auto chain_error_handler(Continuation&& continuation, Callback&& callback, + Executor&& executor) { + static_assert(is_continuation>{}, + "Expected a continuation!"); + + // The current hint will also be the next one + auto hint = hint_of(traits::identity_of(continuation)); + + // TODO consume only the data here so the freeze isn't needed + auto ownership_ = attorney::ownership_of(continuation); + continuation.freeze(); + + return attorney::create( + [ + continuation = std::forward(continuation), + callback = std::forward(callback), + executor = std::forward(executor) + ](auto&& next_callback) mutable { + // Invokes a continuation with a given callback. + // Passes the next callback to the resulting continuable or + // invokes the next callback directly if possible. + // + // For example given: + // - Continuation: continuation<[](auto&& callback) { callback("hi"); + // }> + // - Callback: [](std::string) { } + // - NextCallback: []() { } + /*using Hint = decltype(hint_of(traits::identity_of(continuation))); + result_proxy, + std::decay_t, + std::decay_t> + proxy{std::move(partial_callable), std::move(executor), + std::forward(next_callback)};*/ + + // Invoke the continuation with a proxy callback. + // The proxy callback is responsible for passing + // the result to the callback as well as decorating it. + /*attorney::invoke_continuation(std::forward(continuation), + std::move(proxy));*/ + }, + hint, ownership_); +} + /// Workaround for GCC bug: /// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64095 struct empty_callback { @@ -431,8 +504,7 @@ auto wrap_continuation(Continuation&& continuation) { return supplier_callback>( std::forward(continuation)); } -} // end namespace base - +} // namespace base } // namespace detail } // namespace cti diff --git a/include/continuable/detail/composition.hpp b/include/continuable/detail/composition.hpp index 5995ffd..c2938d4 100644 --- a/include/continuable/detail/composition.hpp +++ b/include/continuable/detail/composition.hpp @@ -70,7 +70,7 @@ template constexpr auto make_hint_of(traits::identity args) noexcept { return args; // Identity is equal to signature_hint_tag } -} // end namespace detail +} // namespace detail /// Extracts the signature hint of a given continuation and it's optional /// present hint arguments. @@ -101,7 +101,7 @@ constexpr auto extract(traits::identity /*type*/, return detail::make_hint_of(hint); }); } -} // end namespace annotating +} // namespace annotating namespace detail { template @@ -198,7 +198,7 @@ private: std::call_once(flag_, std::move(callback_), std::forward(args)...); } }; -} // end namespace detail +} // namespace detail /// Adds the given continuation tuple to the left composition template diff --git a/include/continuable/detail/traits.hpp b/include/continuable/detail/traits.hpp index 2d31a43..c9b6de4 100644 --- a/include/continuable/detail/traits.hpp +++ b/include/continuable/detail/traits.hpp @@ -165,7 +165,7 @@ namespace detail { // See http://stackoverflow.com/questions/35753920 for details. template struct deduce_to_void : std::common_type {}; -} // end namespace detail +} // namespace detail /// C++17 like void_t type template @@ -204,7 +204,7 @@ constexpr auto static_if_impl(std::false_type, Type&& type, FalseCallback&& falseCallback) { return std::forward(falseCallback)(std::forward(type)); } -} // end namespace detail +} // namespace detail /// Returns the pack size of the given type template diff --git a/include/continuable/detail/util.hpp b/include/continuable/detail/util.hpp index d98ab39..31b117e 100644 --- a/include/continuable/detail/util.hpp +++ b/include/continuable/detail/util.hpp @@ -64,7 +64,7 @@ struct is_invokable_impl< T, std::tuple, traits::void_t()(std::declval()...))>> : std::common_type {}; -} // end namespace detail +} // namespace detail /// Deduces to a std::true_type if the given type is callable with the arguments /// inside the given tuple. @@ -148,7 +148,7 @@ auto partial_invoke_impl_shortcut(std::false_type failed, T&& callable, failed, std::forward(callable), std::forward_as_tuple(std::forward(args)...)); } -} // end namespace detail +} // namespace detail /// Partially invokes the given callable with the given arguments. ///