#ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED
#define BOOST_LEAF_CAPTURE_HPP_INCLUDED
-// Copyright (c) 2018-2020 Emil Dotchevski and Reverge Studios, Inc.
+// Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc.
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-#ifndef BOOST_LEAF_ENABLE_WARNINGS
-# if defined(__clang__)
-# pragma clang system_header
-# elif (__GNUC__*100+__GNUC_MINOR__>301)
-# pragma GCC system_header
-# elif defined(_MSC_VER)
-# pragma warning(push,1)
-# endif
-#endif
-
+#include <boost/leaf/config.hpp>
#include <boost/leaf/exception.hpp>
#include <boost/leaf/on_error.hpp>
+#if BOOST_LEAF_CFG_CAPTURE
+
namespace boost { namespace leaf {
- namespace leaf_detail
- {
- template <class R, bool IsResult = is_result_type<R>::value>
- struct is_result_tag;
+namespace leaf_detail
+{
+ template <class R, bool IsResult = is_result_type<R>::value>
+ struct is_result_tag;
- template <class R>
- struct is_result_tag<R, false>
- {
- };
+ template <class R>
+ struct is_result_tag<R, false>
+ {
+ };
- template <class R>
- struct is_result_tag<R, true>
- {
- };
- }
+ template <class R>
+ struct is_result_tag<R, true>
+ {
+ };
+}
#ifdef BOOST_LEAF_NO_EXCEPTIONS
- namespace leaf_detail
+namespace leaf_detail
+{
+ template <class R, class F, class... A>
+ inline
+ decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
+ capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a) noexcept
{
- template <class R, class F, class... A>
- inline
- decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
- capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a) noexcept
- {
- auto active_context = activate_context(*ctx);
- return std::forward<F>(f)(std::forward<A>(a)...);
- }
+ auto active_context = activate_context(*ctx);
+ return std::forward<F>(f)(std::forward<A>(a)...);
+ }
- template <class R, class F, class... A>
- inline
- decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
- capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a) noexcept
+ template <class R, class F, class... A>
+ inline
+ decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
+ capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a) noexcept
+ {
+ auto active_context = activate_context(*ctx);
+ if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
+ return r;
+ else
{
- auto active_context = activate_context(*ctx);
- if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
- return r;
- else
- {
- ctx->captured_id_ = r.error();
- return std::move(ctx);
- }
+ ctx->captured_id_ = r.error();
+ return std::move(ctx);
}
+ }
- template <class R, class Future>
- inline
- decltype(std::declval<Future>().get())
- future_get_impl(is_result_tag<R, false>, Future & fut) noexcept
- {
- return fut.get();
- }
+ template <class R, class Future>
+ inline
+ decltype(std::declval<Future>().get())
+ future_get_impl(is_result_tag<R, false>, Future & fut) noexcept
+ {
+ return fut.get();
+ }
- template <class R, class Future>
- inline
- decltype(std::declval<Future>().get())
- future_get_impl(is_result_tag<R, true>, Future & fut) noexcept
- {
- if( auto r = fut.get() )
- return r;
- else
- return error_id(r.error()); // unloads
- }
+ template <class R, class Future>
+ inline
+ decltype(std::declval<Future>().get())
+ future_get_impl(is_result_tag<R, true>, Future & fut) noexcept
+ {
+ if( auto r = fut.get() )
+ return r;
+ else
+ return error_id(r.error()); // unloads
}
+}
#else
- namespace leaf_detail
+namespace leaf_detail
+{
+ class capturing_exception:
+ public std::exception
{
- class capturing_exception:
- public std::exception
- {
- std::exception_ptr ex_;
- context_ptr ctx_;
-
- public:
-
- capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept:
- ex_(std::move(ex)),
- ctx_(std::move(ctx))
- {
- BOOST_LEAF_ASSERT(ex_);
- BOOST_LEAF_ASSERT(ctx_);
- BOOST_LEAF_ASSERT(ctx_->captured_id_);
- }
-
- [[noreturn]] void unload_and_rethrow_original_exception() const
- {
- BOOST_LEAF_ASSERT(ctx_->captured_id_);
- auto active_context = activate_context(*ctx_);
- id_factory<>::current_id = ctx_->captured_id_.value();
- std::rethrow_exception(ex_);
- }
+ std::exception_ptr ex_;
+ context_ptr ctx_;
- template <class CharT, class Traits>
- void print( std::basic_ostream<CharT, Traits> & os ) const
- {
- ctx_->print(os);
- }
- };
+ public:
- template <class R, class F, class... A>
- inline
- decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
- capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a)
+ capturing_exception(std::exception_ptr && ex, context_ptr && ctx) noexcept:
+ ex_(std::move(ex)),
+ ctx_(std::move(ctx))
{
- auto active_context = activate_context(*ctx);
- error_monitor cur_err;
- try
- {
- return std::forward<F>(f)(std::forward<A>(a)...);
- }
- catch( capturing_exception const & )
- {
- throw;
- }
- catch( exception_base const & e )
- {
- ctx->captured_id_ = e.get_error_id();
- throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
- }
- catch(...)
- {
- ctx->captured_id_ = cur_err.assigned_error_id();
- throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
- }
+ BOOST_LEAF_ASSERT(ex_);
+ BOOST_LEAF_ASSERT(ctx_);
+ BOOST_LEAF_ASSERT(ctx_->captured_id_);
}
- template <class R, class F, class... A>
- inline
- decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
- capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a)
+ [[noreturn]] void unload_and_rethrow_original_exception() const
{
- auto active_context = activate_context(*ctx);
- error_monitor cur_err;
- try
- {
- if( auto && r = std::forward<F>(f)(std::forward<A>(a)...) )
- return std::move(r);
- else
- {
- ctx->captured_id_ = r.error();
- return std::move(ctx);
- }
- }
- catch( capturing_exception const & )
- {
- throw;
- }
- catch( exception_base const & e )
- {
- ctx->captured_id_ = e.get_error_id();
- throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
- }
- catch(...)
- {
- ctx->captured_id_ = cur_err.assigned_error_id();
- throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
- }
+ BOOST_LEAF_ASSERT(ctx_->captured_id_);
+ tls::write_uint32<tls_tag_id_factory_current_id>(ctx_->captured_id_.value());
+ ctx_->propagate(ctx_->captured_id_);
+ std::rethrow_exception(ex_);
}
- template <class R, class Future>
- inline
- decltype(std::declval<Future>().get())
- future_get_impl(is_result_tag<R, false>, Future & fut )
+ template <class CharT, class Traits>
+ void print( std::basic_ostream<CharT, Traits> & os ) const
{
- try
- {
- return fut.get();
- }
- catch( capturing_exception const & cap )
- {
- cap.unload_and_rethrow_original_exception();
- }
+ ctx_->print(os);
}
+ };
- template <class R, class Future>
- inline
- decltype(std::declval<Future>().get())
- future_get_impl(is_result_tag<R, true>, Future & fut )
+ template <class R, class F, class... A>
+ inline
+ decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
+ capture_impl(is_result_tag<R, false>, context_ptr && ctx, F && f, A... a)
+ {
+ auto active_context = activate_context(*ctx);
+ error_monitor cur_err;
+ try
{
- try
- {
- if( auto r = fut.get() )
- return r;
- else
- return error_id(r.error()); // unloads
- }
- catch( capturing_exception const & cap )
- {
- cap.unload_and_rethrow_original_exception();
- }
+ return std::forward<F>(f)(std::forward<A>(a)...);
+ }
+ catch( capturing_exception const & )
+ {
+ throw;
+ }
+ catch( exception_base const & e )
+ {
+ ctx->captured_id_ = e.get_error_id();
+ throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
+ }
+ catch(...)
+ {
+ ctx->captured_id_ = cur_err.assigned_error_id();
+ throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
}
}
-#endif
-
- template <class F, class... A>
+ template <class R, class F, class... A>
inline
decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
- capture(context_ptr && ctx, F && f, A... a)
+ capture_impl(is_result_tag<R, true>, context_ptr && ctx, F && f, A... a)
{
- using namespace leaf_detail;
- return capture_impl(is_result_tag<decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))>(), std::move(ctx), std::forward<F>(f), std::forward<A>(a)...);
+ auto active_context = activate_context(*ctx);
+ error_monitor cur_err;
+ try
+ {
+ if( auto && r = std::forward<F>(f)(std::forward<A>(a)...) )
+ return std::move(r);
+ else
+ {
+ ctx->captured_id_ = r.error();
+ return std::move(ctx);
+ }
+ }
+ catch( capturing_exception const & )
+ {
+ throw;
+ }
+ catch( exception_base const & e )
+ {
+ ctx->captured_id_ = e.get_error_id();
+ throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
+ }
+ catch(...)
+ {
+ ctx->captured_id_ = cur_err.assigned_error_id();
+ throw_exception( capturing_exception(std::current_exception(), std::move(ctx)) );
+ }
}
- template <class Future>
+ template <class R, class Future>
inline
decltype(std::declval<Future>().get())
- future_get( Future & fut )
- {
- using namespace leaf_detail;
- return future_get_impl(is_result_tag<decltype(std::declval<Future>().get())>(), fut);
- }
-
- ////////////////////////////////////////
-
-#ifndef BOOST_LEAF_NO_EXCEPTIONS
-
- template <class T>
- class result;
-
- namespace leaf_detail
+ future_get_impl(is_result_tag<R, false>, Future & fut )
{
- inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<> )
+ try
{
- return leaf::new_error(std::current_exception());
+ return fut.get();
}
-
- template <class Ex1, class... Ex>
- inline error_id catch_exceptions_helper( std::exception const & ex, leaf_detail_mp11::mp_list<Ex1,Ex...> )
+ catch( capturing_exception const & cap )
{
- if( Ex1 const * p = dynamic_cast<Ex1 const *>(&ex) )
- return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ }).load(*p);
- else
- return catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>{ });
+ cap.unload_and_rethrow_original_exception();
}
-
- template <class T>
- struct deduce_exception_to_result_return_type_impl
- {
- using type = result<T>;
- };
-
- template <class T>
- struct deduce_exception_to_result_return_type_impl<result<T>>
- {
- using type = result<T>;
- };
-
- template <class T>
- using deduce_exception_to_result_return_type = typename deduce_exception_to_result_return_type_impl<T>::type;
}
- template <class... Ex, class F>
+ template <class R, class Future>
inline
- leaf_detail::deduce_exception_to_result_return_type<leaf_detail::fn_return_type<F>>
- exception_to_result( F && f ) noexcept
+ decltype(std::declval<Future>().get())
+ future_get_impl(is_result_tag<R, true>, Future & fut )
{
try
{
- return std::forward<F>(f)();
- }
- catch( std::exception const & ex )
- {
- return leaf_detail::catch_exceptions_helper(ex, leaf_detail_mp11::mp_list<Ex...>());
+ if( auto r = fut.get() )
+ return r;
+ else
+ return error_id(r.error()); // unloads
}
- catch(...)
+ catch( capturing_exception const & cap )
{
- return leaf::new_error(std::current_exception());
+ cap.unload_and_rethrow_original_exception();
}
}
+}
#endif
+template <class F, class... A>
+inline
+decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
+capture(context_ptr && ctx, F && f, A... a)
+{
+ using namespace leaf_detail;
+ return capture_impl(is_result_tag<decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))>(), std::move(ctx), std::forward<F>(f), std::forward<A>(a)...);
+}
+
+template <class Future>
+inline
+decltype(std::declval<Future>().get())
+future_get( Future & fut )
+{
+ using namespace leaf_detail;
+ return future_get_impl(is_result_tag<decltype(std::declval<Future>().get())>(), fut);
+}
+
} }
#endif
+
+#endif