diff --git a/.clang-format b/.clang-format index 8225649..f709fc2 100644 --- a/.clang-format +++ b/.clang-format @@ -7,3 +7,5 @@ AllowShortCaseLabelsOnASingleLine: false AlwaysBreakTemplateDeclarations: true BinPackArguments: true FixNamespaceComments: true +MacroBlockBegin: "^CONTINUABLE_BLOCK_.*_BEGIN$" +MacroBlockEnd: "^CONTINUABLE_BLOCK_.*_END$" diff --git a/include/continuable/detail/base.hpp b/include/continuable/detail/base.hpp index 0842b1e..3e0c476 100644 --- a/include/continuable/detail/base.hpp +++ b/include/continuable/detail/base.hpp @@ -151,6 +151,21 @@ public: } }; +#if !defined(CONTINUABLE_WITH_CUSTOM_ERROR_TYPE) && \ + !defined(CONTINUABLE_WITH_NO_EXCEPTIONS) +#define CONTINUABLE_BLOCK_TRY_BEGIN try { +#define CONTINUABLE_BLOCK_TRY_END \ + } \ + catch (...) { \ + std::forward(next_callback)( \ + types::dispatch_error_tag{}, std::current_exception()); \ + } + +#else +#define CONTINUABLE_BLOCK_TRY_BEGIN { +#define CONTINUABLE_BLOCK_TRY_END } +#endif + template constexpr auto make_invoker(T&& invoke, hints::signature_hint_tag) { return invoker, hints::signature_hint_tag>( @@ -167,13 +182,15 @@ invoker_of(traits::identity>) { return make_invoker( [](auto&& callback, auto&& next_callback, auto&&... args) { - auto continuation_ = - util::partial_invoke(std::forward(callback), - std::forward(args)...); + CONTINUABLE_BLOCK_TRY_BEGIN + auto continuation_ = + util::partial_invoke(std::forward(callback), + std::forward(args)...); - attorney::invoke_continuation( - std::move(continuation_), - std::forward(next_callback)); + attorney::invoke_continuation( + std::move(continuation_), + std::forward(next_callback)); + CONTINUABLE_BLOCK_TRY_END }, hint_of(traits::identity_of())); } @@ -183,11 +200,14 @@ template constexpr auto invoker_of(traits::identity) { return make_invoker( [](auto&& callback, auto&& next_callback, auto&&... args) { - auto result = - util::partial_invoke(std::forward(callback), - std::forward(args)...); + CONTINUABLE_BLOCK_TRY_BEGIN + auto result = + util::partial_invoke(std::forward(callback), + std::forward(args)...); - std::forward(next_callback)(std::move(result)); + std::forward(next_callback)( + std::move(result)); + CONTINUABLE_BLOCK_TRY_END }, traits::identity_of()); } @@ -196,10 +216,11 @@ constexpr auto invoker_of(traits::identity) { inline auto invoker_of(traits::identity) { return make_invoker( [](auto&& callback, auto&& next_callback, auto&&... args) { - util::partial_invoke(std::forward(callback), - std::forward(args)...); - - std::forward(next_callback)(); + CONTINUABLE_BLOCK_TRY_BEGIN + util::partial_invoke(std::forward(callback), + std::forward(args)...); + std::forward(next_callback)(); + CONTINUABLE_BLOCK_TRY_END }, traits::identity<>{}); } @@ -208,18 +229,20 @@ inline auto invoker_of(traits::identity) { /// objects where std::get is applicable. inline auto sequenced_unpack_invoker() { return [](auto&& callback, auto&& next_callback, auto&&... args) { - auto result = - util::partial_invoke(std::forward(callback), - std::forward(args)...); + CONTINUABLE_BLOCK_TRY_BEGIN + auto result = + util::partial_invoke(std::forward(callback), + std::forward(args)...); - traits::unpack(std::move(result), [&](auto&&... types) { - /// TODO Add inplace resolution here + traits::unpack(std::move(result), [&](auto&&... types) { + /// TODO Add inplace resolution here - std::forward(next_callback)( - std::forward(types)...); - }); + std::forward(next_callback)( + std::forward(types)...); + }); + CONTINUABLE_BLOCK_TRY_END }; -} +} // namespace decoration // - std::pair -> next_callback(?, ?) template @@ -233,6 +256,9 @@ template constexpr auto invoker_of(traits::identity>) { return make_invoker(sequenced_unpack_invoker(), traits::identity{}); } + +#undef CONTINUABLE_BLOCK_TRY_BEGIN +#undef CONTINUABLE_BLOCK_TRY_END } // namespace decoration /// Invoke the callback immediately @@ -240,18 +266,8 @@ template void packed_dispatch(types::this_thread_executor_tag, Invoker&& invoker, Args&&... args) { - !defined(CONTINUABLE_WITH_NO_EXCEPTIONS) - // Make it possible to throw exceptions from continuations chained - // through `then` or `flow`. - try { - std::forward(invoker)(std::forward(args)...); - } catch (...) { - std::current_exception(); - } -#else // Invoke the callback with the decorated invoker immediately std::forward(invoker)(std::forward(args)...); -#endif } /// Invoke the callback through the given executor