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
0005
0006
0007
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());
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());
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