diff --git a/include/continuable/continuable-base.hpp b/include/continuable/continuable-base.hpp index 938bb77..1048f7f 100644 --- a/include/continuable/continuable-base.hpp +++ b/include/continuable/continuable-base.hpp @@ -225,6 +225,52 @@ public: detail::base::wrap_continuation(std::move(continuation).materialize())); } + /// Main method of the continuable_base to catch exceptions and error codes + /// + /// \param callback The callback which is used to process the current + /// asynchronous error result on arrival. + /// In case the continuable_base is using exceptions, the usage is as + /// shown below: + /// + /// ```cpp + /// http_request("github.com") + /// .then([](std::string github) { }) + /// .catching([](std::exception_ptr ptr) { + /// // Handle the error here + /// try { + /// std::rethrow_exception(ptr); + /// } catch (std::exception& e) { + /// e.what(); // Handle the exception + /// } + /// }); + /// ``` + /// In case exceptions are disabled, `std::error_condition` is + /// used as error result instead of `std::exception_ptr`. + /// ```cpp + /// http_request("github.com") + /// .then([](std::string github) { }) + /// .catching([](std::error_condition error) { + /// // Handle the error here + /// // ... + /// }); + /// ``` + /// + /// \param executor The optional executor which is used to dispatch + /// the callback. See the description in `then` above. + /// + /// \returns Returns a continuable_base with an asynchronous return type + /// depending on the current result type. + /// + /// + /// \since version 2.0.0 + template + auto catching(T&& callback, + E&& executor = detail::base::this_thread_executor_tag{}) && { + /*return detail::base::chain_continuation(std::move(*this).materialize(), + std::forward(callback), + std::forward(executor));*/ + } + /// Invokes both continuable_base objects parallel and calls the /// callback with the result of both continuable_base objects. /// diff --git a/include/continuable/continuable-promise-base.hpp b/include/continuable/continuable-promise-base.hpp new file mode 100644 index 0000000..4ebe29f --- /dev/null +++ b/include/continuable/continuable-promise-base.hpp @@ -0,0 +1,87 @@ + +/** + + /~` _ _ _|_. _ _ |_ | _ + \_,(_)| | | || ||_|(_||_)|(/_ + + https://github.com/Naios/continuable + v2.0.0 + + Copyright(c) 2015 - 2017 Denis Blank + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files(the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and / or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions : + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +**/ + +#ifndef CONTINUABLE_PROMISE_BASE_HPP_INCLUDED__ +#define CONTINUABLE_PROMISE_BASE_HPP_INCLUDED__ + +#include +#include + +#include +#include + +namespace cti { +template +class promise_base { + /// \cond false + // The callback type + Data data_; + /// \endcond + +public: + /// Constructor accepting the data object + explicit promise_base(Data data) : data_(std::move(data)) { + } + + /// Constructor accepting any object convertible to the data object + template , Data>::value>* = nullptr> + promise_base(OData&& data) : data_(std::forward(data)) { + } + + /// \cond false + promise_base(promise_base&&) = default; + promise_base(promise_base const&) = default; + + promise_base& operator=(promise_base&&) = default; + promise_base& operator=(promise_base const&) = default; + /// \endcond + + /// Resolves the continuation with the given values + template + void set_value(Args&&... args) { + data_(detail::base::dispatch_result{}, std::forward(args)...); + } + + /// Resolves the continuation with the given values + template + void operator()(Args&&... args) { + data_(detail::base::dispatch_result{}, std::forward(args)...); + } + + /// Resolves the continuation with the given error variable. + template + void set_error(Arg&& arg) { + data_(detail::base::dispatch_error{}, std::forward(arg)); + } +}; +} // end namespace cti + +#endif // CONTINUABLE_PROMISE_BASE_HPP_INCLUDED__ diff --git a/include/continuable/detail/base.hpp b/include/continuable/detail/base.hpp index 906ab83..105a4fb 100644 --- a/include/continuable/detail/base.hpp +++ b/include/continuable/detail/base.hpp @@ -57,7 +57,12 @@ namespace detail { /// base::finalize_continuation(base::continuation continuation) /// -> void namespace base { +/// A tag which is used to execute the continuation inside the current thread struct this_thread_executor_tag {}; +/// A tag which is used to continue with a real result +struct dispatch_result {}; +/// A tag which is used to continue with an error +struct dispatch_error {}; /// Returns the signature hint of the given continuable template @@ -285,7 +290,7 @@ void invoke_proxy(hints::signature_hint_tag, Executor&& executor, NextCallback&& nextCallback) { // Invoke the continuation with a proxy callback. - // The proxy callback is responsible for passing the + // The proxy callback is responsible for passing // the result to the callback as well as decorating it. attorney::invoke_continuation(std::forward(continuation), [ callback = std::forward(callback), @@ -351,11 +356,11 @@ auto chain_continuation(Continuation&& continuation, Callback&& callback, continuation = std::forward(continuation), partial_callable = std::move(partial_callable), executor = std::forward(executor) - ](auto&& nextCallback) mutable { + ](auto&& next_callback) mutable { invoke_proxy(hint_of(traits::identity_of(continuation)), std::move(continuation), std::move(partial_callable), std::move(executor), - std::forward(nextCallback)); + std::forward(next_callback)); }, next_hint, ownership_); } diff --git a/include/continuable/detail/features.hpp b/include/continuable/detail/features.hpp index 5294a23..f007053 100644 --- a/include/continuable/detail/features.hpp +++ b/include/continuable/detail/features.hpp @@ -30,7 +30,20 @@ #ifndef CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED__ #define CONTINUABLE_DETAIL_FEATURES_HPP_INCLUDED__ -#include +// Defines CONTINUABLE_WITH_NO_EXCEPTIONS when exception support is disabled +#if defined(_MSC_VER) +#if !defined(_HAS_EXCEPTIONS) || (_HAS_EXCEPTIONS == 0) +#define CONTINUABLE_WITH_NO_EXCEPTIONS +#endif +#elif defined(__clang__) +#if !(__EXCEPTIONS && __has_feature(cxx_exceptions)) +#define CONTINUABLE_WITH_NO_EXCEPTIONS +#endif +#elif defined(__GNUC__) +#if !__EXCEPTIONS +#define CONTINUABLE_WITH_NO_EXCEPTIONS +#endif +#endif #undef CONTINUABLE_HAS_CXX17_CONSTEXPR_IF #undef CONTINUABLE_HAS_CXX17_FOLD_EXPRESSION diff --git a/test/playground/CMakeLists.txt b/test/playground/CMakeLists.txt index d6eb3e6..6549492 100644 --- a/test/playground/CMakeLists.txt +++ b/test/playground/CMakeLists.txt @@ -1,6 +1,7 @@ set(LIB_SOURCES ${CMAKE_SOURCE_DIR}/include/continuable/continuable.hpp ${CMAKE_SOURCE_DIR}/include/continuable/continuable-base.hpp + ${CMAKE_SOURCE_DIR}/include/continuable/continuable-promise-base.hpp ${CMAKE_SOURCE_DIR}/include/continuable/continuable-testing.hpp) set(LIB_SOURCES_DETAIL ${CMAKE_SOURCE_DIR}/include/continuable/detail/base.hpp