Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:11

0001 #ifndef BOOST_LEAF_CAPTURE_HPP_INCLUDED
0002 #define BOOST_LEAF_CAPTURE_HPP_INCLUDED
0003 
0004 // Copyright 2018-2023 Emil Dotchevski and Reverge Studios, Inc.
0005 
0006 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0007 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 #include <boost/leaf/config.hpp>
0010 #include <boost/leaf/exception.hpp>
0011 #include <boost/leaf/on_error.hpp>
0012 
0013 #if BOOST_LEAF_CFG_CAPTURE
0014 
0015 namespace boost { namespace leaf {
0016 
0017 namespace leaf_detail
0018 {
0019     template <class R, bool IsResult = is_result_type<R>::value>
0020     struct is_result_tag;
0021 
0022     template <class R>
0023     struct is_result_tag<R, false>
0024     {
0025     };
0026 
0027     template <class R>
0028     struct is_result_tag<R, true>
0029     {
0030     };
0031 }
0032 
0033 #ifdef BOOST_LEAF_NO_EXCEPTIONS
0034 
0035 namespace leaf_detail
0036 {
0037     template <class R, class F, class... A, class ContextPtr>
0038     inline
0039     decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0040     capture_impl(is_result_tag<R, false>, ContextPtr && ctx, F && f, A... a) noexcept
0041     {
0042         auto active_context = activate_context(*ctx);
0043         return std::forward<F>(f)(std::forward<A>(a)...);
0044     }
0045 
0046     template <class R, class F, class... A, class ContextPtr>
0047     inline
0048     decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0049     capture_impl(is_result_tag<R, true>, ContextPtr && ctx, F && f, A... a) noexcept
0050     {
0051         auto active_context = activate_context(*ctx);
0052         if( auto r = std::forward<F>(f)(std::forward<A>(a)...) )
0053             return r;
0054         else
0055         {
0056             ctx->captured_id_ = r.error();
0057             return std::forward<ContextPtr>(ctx);
0058         }
0059     }
0060 
0061     template <class R, class Future>
0062     inline
0063     decltype(std::declval<Future>().get())
0064     future_get_impl(is_result_tag<R, false>, Future & fut) noexcept
0065     {
0066         return fut.get();
0067     }
0068 
0069     template <class R, class Future>
0070     inline
0071     decltype(std::declval<Future>().get())
0072     future_get_impl(is_result_tag<R, true>, Future & fut) noexcept
0073     {
0074         if( auto r = fut.get() )
0075             return r;
0076         else
0077             return error_id(r.error()); // unloads
0078     }
0079 }
0080 
0081 #else
0082 
0083 namespace leaf_detail
0084 {
0085     class capturing_exception:
0086         public std::exception
0087     {
0088         std::exception_ptr ex_;
0089         context_ptr ctx_;
0090 
0091     public:
0092 
0093         template <class ContextPtr>
0094         capturing_exception(std::exception_ptr && ex, ContextPtr && ctx) noexcept:
0095             ex_(std::move(ex)),
0096             ctx_(std::forward<ContextPtr>(ctx))
0097         {
0098             BOOST_LEAF_ASSERT(ex_);
0099             BOOST_LEAF_ASSERT(ctx_);
0100             BOOST_LEAF_ASSERT(ctx_->captured_id_);
0101         }
0102 
0103         [[noreturn]] void unload_and_rethrow_original_exception() const
0104         {
0105             BOOST_LEAF_ASSERT(ctx_->captured_id_);
0106             tls::write_uint<tls_tag_id_factory_current_id>(unsigned(ctx_->captured_id_.value()));
0107             ctx_->propagate(ctx_->captured_id_);
0108             std::rethrow_exception(ex_);
0109         }
0110     };
0111 
0112     template <class R, class F, class... A, class ContextPtr>
0113     inline
0114     decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0115     capture_impl(is_result_tag<R, false>, ContextPtr && ctx, F && f, A... a)
0116     {
0117         auto active_context = activate_context(*ctx);
0118         error_monitor cur_err;
0119         try
0120         {
0121             return std::forward<F>(f)(std::forward<A>(a)...);
0122         }
0123         catch( capturing_exception const & )
0124         {
0125             throw;
0126         }
0127         catch( exception_base const & e )
0128         {
0129             ctx->captured_id_ = e.get_error_id();
0130             leaf_detail::throw_exception_impl( capturing_exception(std::current_exception(), std::forward<ContextPtr>(ctx)) );
0131         }
0132         catch(...)
0133         {
0134             ctx->captured_id_ = cur_err.assigned_error_id();
0135             leaf_detail::throw_exception_impl( capturing_exception(std::current_exception(), std::forward<ContextPtr>(ctx)) );
0136         }
0137     }
0138 
0139     template <class R, class F, class... A, class ContextPtr>
0140     inline
0141     decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0142     capture_impl(is_result_tag<R, true>, ContextPtr && ctx, F && f, A... a)
0143     {
0144         auto active_context = activate_context(*ctx);
0145         error_monitor cur_err;
0146         try
0147         {
0148             if( auto && r = std::forward<F>(f)(std::forward<A>(a)...) )
0149                 return std::move(r);
0150             else
0151             {
0152                 ctx->captured_id_ = r.error();
0153                 return std::forward<ContextPtr>(ctx);
0154             }
0155         }
0156         catch( capturing_exception const & )
0157         {
0158             throw;
0159         }
0160         catch( exception_base const & e )
0161         {
0162             ctx->captured_id_ = e.get_error_id();
0163             leaf_detail::throw_exception_impl( capturing_exception(std::current_exception(), std::forward<ContextPtr>(ctx)) );
0164         }
0165         catch(...)
0166         {
0167             ctx->captured_id_ = cur_err.assigned_error_id();
0168             leaf_detail::throw_exception_impl( capturing_exception(std::current_exception(), std::forward<ContextPtr>(ctx)) );
0169         }
0170     }
0171 
0172     template <class R, class Future>
0173     inline
0174     decltype(std::declval<Future>().get())
0175     future_get_impl(is_result_tag<R, false>, Future & fut )
0176     {
0177         try
0178         {
0179             return fut.get();
0180         }
0181         catch( capturing_exception const & cap )
0182         {
0183             cap.unload_and_rethrow_original_exception();
0184         }
0185     }
0186 
0187     template <class R, class Future>
0188     inline
0189     decltype(std::declval<Future>().get())
0190     future_get_impl(is_result_tag<R, true>, Future & fut )
0191     {
0192         try
0193         {
0194             if( auto r = fut.get() )
0195                 return r;
0196             else
0197                 return error_id(r.error()); // unloads
0198         }
0199         catch( capturing_exception const & cap )
0200         {
0201             cap.unload_and_rethrow_original_exception();
0202         }
0203     }
0204 }
0205 
0206 #endif
0207 
0208 template <class F, class... A>
0209 inline
0210 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0211 capture(context_ptr const & ctx, F && f, A... a)
0212 {
0213     using namespace leaf_detail;
0214     return capture_impl(is_result_tag<decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))>(), ctx, std::forward<F>(f), std::forward<A>(a)...);
0215 }
0216 
0217 template <class F, class... A>
0218 inline
0219 decltype(std::declval<F>()(std::forward<A>(std::declval<A>())...))
0220 capture(context_ptr && ctx, F && f, A... a)
0221 {
0222     using namespace leaf_detail;
0223     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)...);
0224 }
0225 
0226 template <class Future>
0227 inline
0228 decltype(std::declval<Future>().get())
0229 future_get( Future & fut )
0230 {
0231     using namespace leaf_detail;
0232     return future_get_impl(is_result_tag<decltype(std::declval<Future>().get())>(), fut);
0233 }
0234 
0235 } }
0236 
0237 #endif
0238 
0239 #endif