Back to home page

EIC code displayed by LXR

 
 

    


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

0001 #ifndef BOOST_LEAF_CONTEXT_HPP_INCLUDED
0002 #define BOOST_LEAF_CONTEXT_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/error.hpp>
0011 
0012 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
0013 #   include <thread>
0014 #endif
0015 
0016 namespace boost { namespace leaf {
0017 
0018 class error_info;
0019 class diagnostic_info;
0020 class verbose_diagnostic_info;
0021 
0022 template <class>
0023 struct is_predicate: std::false_type
0024 {
0025 };
0026 
0027 namespace leaf_detail
0028 {
0029     template <class T>
0030     struct is_exception: std::is_base_of<std::exception, typename std::decay<T>::type>
0031     {
0032     };
0033 
0034     template <class E>
0035     struct handler_argument_traits;
0036 
0037     template <class E, bool IsPredicate = is_predicate<E>::value>
0038     struct handler_argument_traits_defaults;
0039 
0040     template <class E>
0041     struct handler_argument_traits_defaults<E, false>
0042     {
0043         using error_type = typename std::decay<E>::type;
0044         constexpr static bool always_available = false;
0045 
0046         template <class Tup>
0047         BOOST_LEAF_CONSTEXPR static error_type const * check( Tup const &, error_info const & ) noexcept;
0048 
0049         template <class Tup>
0050         BOOST_LEAF_CONSTEXPR static error_type * check( Tup &, error_info const & ) noexcept;
0051 
0052         template <class Tup>
0053         BOOST_LEAF_CONSTEXPR static E get( Tup & tup, error_info const & ei ) noexcept
0054         {
0055             return *check(tup, ei);
0056         }
0057 
0058         static_assert(!is_predicate<error_type>::value, "Handlers must take predicate arguments by value");
0059         static_assert(!std::is_same<E, error_info>::value, "Handlers must take leaf::error_info arguments by const &");
0060         static_assert(!std::is_same<E, diagnostic_info>::value, "Handlers must take leaf::diagnostic_info arguments by const &");
0061         static_assert(!std::is_same<E, verbose_diagnostic_info>::value, "Handlers must take leaf::verbose_diagnostic_info arguments by const &");
0062     };
0063 
0064     template <class Pred>
0065     struct handler_argument_traits_defaults<Pred, true>: handler_argument_traits<typename Pred::error_type>
0066     {
0067         using base = handler_argument_traits<typename Pred::error_type>;
0068         static_assert(!base::always_available, "Predicates can't use types that are always_available");
0069 
0070         template <class Tup>
0071         BOOST_LEAF_CONSTEXPR static bool check( Tup const & tup, error_info const & ei ) noexcept
0072         {
0073             auto e = base::check(tup, ei);
0074             return e && Pred::evaluate(*e);
0075         }
0076 
0077         template <class Tup>
0078         BOOST_LEAF_CONSTEXPR static Pred get( Tup const & tup, error_info const & ei ) noexcept
0079         {
0080             return Pred{*base::check(tup, ei)};
0081         }
0082     };
0083 
0084     template <class E>
0085     struct handler_argument_always_available
0086     {
0087         using error_type = E;
0088         constexpr static bool always_available = true;
0089 
0090         template <class Tup>
0091         BOOST_LEAF_CONSTEXPR static bool check( Tup &, error_info const & ) noexcept
0092         {
0093             return true;
0094         }
0095     };
0096 
0097     template <class E>
0098     struct handler_argument_traits: handler_argument_traits_defaults<E>
0099     {
0100     };
0101 
0102     template <>
0103     struct handler_argument_traits<void>
0104     {
0105         using error_type = void;
0106         constexpr static bool always_available = false;
0107 
0108         template <class Tup>
0109         BOOST_LEAF_CONSTEXPR static std::exception const * check( Tup const &, error_info const & ) noexcept;
0110     };
0111 
0112     template <class E>
0113     struct handler_argument_traits<E &&>
0114     {
0115         static_assert(sizeof(E) == 0, "Error handlers may not take rvalue ref arguments");
0116     };
0117 
0118     template <class E>
0119     struct handler_argument_traits<E *>: handler_argument_always_available<typename std::remove_const<E>::type>
0120     {
0121         template <class Tup>
0122         BOOST_LEAF_CONSTEXPR static E * get( Tup & tup, error_info const & ei) noexcept
0123         {
0124             return handler_argument_traits_defaults<E>::check(tup, ei);
0125         }
0126     };
0127 
0128     template <>
0129     struct handler_argument_traits<error_info const &>: handler_argument_always_available<void>
0130     {
0131         template <class Tup>
0132         BOOST_LEAF_CONSTEXPR static error_info const & get( Tup const &, error_info const & ei ) noexcept
0133         {
0134             return ei;
0135         }
0136     };
0137 
0138     template <class E>
0139     struct handler_argument_traits_require_by_value
0140     {
0141         static_assert(sizeof(E) == 0, "Error handlers must take this type by value");
0142     };
0143 }
0144 
0145 ////////////////////////////////////////
0146 
0147 namespace leaf_detail
0148 {
0149     template <int I, class Tuple>
0150     struct tuple_for_each
0151     {
0152         BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept
0153         {
0154             static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
0155             tuple_for_each<I-1,Tuple>::activate(tup);
0156             std::get<I-1>(tup).activate();
0157         }
0158 
0159         BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept
0160         {
0161             static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
0162             std::get<I-1>(tup).deactivate();
0163             tuple_for_each<I-1,Tuple>::deactivate(tup);
0164         }
0165 
0166         BOOST_LEAF_CONSTEXPR static void propagate( Tuple & tup, int err_id ) noexcept
0167         {
0168             static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
0169             auto & sl = std::get<I-1>(tup);
0170             sl.propagate(err_id);
0171             tuple_for_each<I-1,Tuple>::propagate(tup, err_id);
0172         }
0173 
0174         BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple & tup, int err_id ) noexcept
0175         {
0176             static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
0177             BOOST_LEAF_ASSERT(err_id != 0);
0178             auto & sl = std::get<I-1>(tup);
0179             if( sl.has_value(err_id) )
0180                 (void) load_slot<false>(err_id, std::move(sl).value(err_id));
0181             tuple_for_each<I-1,Tuple>::propagate_captured(tup, err_id);
0182         }
0183 
0184         template <class CharT, class Traits>
0185         static void print( std::basic_ostream<CharT, Traits> & os, void const * tup, int key_to_print )
0186         {
0187             BOOST_LEAF_ASSERT(tup != nullptr);
0188             tuple_for_each<I-1,Tuple>::print(os, tup, key_to_print);
0189             std::get<I-1>(*static_cast<Tuple const *>(tup)).print(os, key_to_print);
0190         }
0191     };
0192 
0193     template <class Tuple>
0194     struct tuple_for_each<0, Tuple>
0195     {
0196         BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { }
0197         BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { }
0198         BOOST_LEAF_CONSTEXPR static void propagate( Tuple &, int ) noexcept { }
0199         BOOST_LEAF_CONSTEXPR static void propagate_captured( Tuple &, int ) noexcept { }
0200         template <class CharT, class Traits>
0201         BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, void const *, int ) { }
0202     };
0203 }
0204 
0205 ////////////////////////////////////////////
0206 
0207 #if BOOST_LEAF_CFG_DIAGNOSTICS
0208 
0209 namespace leaf_detail
0210 {
0211     template <class T> struct requires_unexpected { constexpr static bool value = false; };
0212     template <class T> struct requires_unexpected<T const> { constexpr static bool value = requires_unexpected<T>::value; };
0213     template <class T> struct requires_unexpected<T const &> { constexpr static bool value = requires_unexpected<T>::value; };
0214     template <class T> struct requires_unexpected<T const *> { constexpr static bool value = requires_unexpected<T>::value; };
0215     template <> struct requires_unexpected<e_unexpected_count> { constexpr static bool value = true; };
0216     template <> struct requires_unexpected<e_unexpected_info> { constexpr static bool value = true; };
0217 
0218     template <class L>
0219     struct unexpected_requested;
0220 
0221     template <template <class ...> class L>
0222     struct unexpected_requested<L<>>
0223     {
0224         constexpr static bool value = false;
0225     };
0226 
0227     template <template <class...> class L, template <class> class S, class Car, class... Cdr>
0228     struct unexpected_requested<L<S<Car>, S<Cdr>...>>
0229     {
0230         constexpr static bool value = requires_unexpected<Car>::value || unexpected_requested<L<S<Cdr>...>>::value;
0231     };
0232 }
0233 
0234 #endif
0235 
0236 ////////////////////////////////////////////
0237 
0238 namespace leaf_detail
0239 {
0240     template <class T> struct does_not_participate_in_context_deduction: std::is_abstract<T> { };
0241     template <> struct does_not_participate_in_context_deduction<void>: std::true_type { };
0242     template <> struct does_not_participate_in_context_deduction<error_id>: std::true_type { };
0243 
0244     template <class L>
0245     struct deduce_e_type_list;
0246 
0247     template <template<class...> class L, class... T>
0248     struct deduce_e_type_list<L<T...>>
0249     {
0250         using type =
0251             leaf_detail_mp11::mp_remove_if<
0252                 leaf_detail_mp11::mp_unique<
0253                     leaf_detail_mp11::mp_list<typename handler_argument_traits<T>::error_type...>
0254                 >,
0255                 does_not_participate_in_context_deduction
0256             >;
0257     };
0258 
0259     template <class L>
0260     struct deduce_e_tuple_impl;
0261 
0262     template <template <class...> class L, class... E>
0263     struct deduce_e_tuple_impl<L<E...>>
0264     {
0265         using type = std::tuple<slot<E>...>;
0266     };
0267 
0268     template <class... E>
0269     using deduce_e_tuple = typename deduce_e_tuple_impl<typename deduce_e_type_list<leaf_detail_mp11::mp_list<E...>>::type>::type;
0270 }
0271 
0272 ////////////////////////////////////////////
0273 
0274 template <class... E>
0275 class context
0276 {
0277     context( context const & ) = delete;
0278     context & operator=( context const & ) = delete;
0279 
0280     using Tup = leaf_detail::deduce_e_tuple<E...>;
0281     Tup tup_;
0282     bool is_active_;
0283 
0284 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
0285     std::thread::id thread_id_;
0286 #endif
0287 
0288 protected:
0289 
0290     BOOST_LEAF_CONSTEXPR error_id propagate_captured_errors( error_id err_id ) noexcept
0291     {
0292         leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate_captured(tup_, err_id.value());
0293         return err_id;
0294     }
0295 
0296 public:
0297 
0298     BOOST_LEAF_CONSTEXPR context( context && x ) noexcept:
0299         tup_(std::move(x.tup_)),
0300         is_active_(false)
0301     {
0302         BOOST_LEAF_ASSERT(!x.is_active());
0303     }
0304 
0305     BOOST_LEAF_CONSTEXPR context() noexcept:
0306         is_active_(false)
0307     {
0308     }
0309 
0310     ~context() noexcept
0311     {
0312         BOOST_LEAF_ASSERT(!is_active());
0313     }
0314 
0315     BOOST_LEAF_CONSTEXPR Tup const & tup() const noexcept
0316     {
0317         return tup_;
0318     }
0319 
0320     BOOST_LEAF_CONSTEXPR Tup & tup() noexcept
0321     {
0322         return tup_;
0323     }
0324 
0325     BOOST_LEAF_CONSTEXPR void activate() noexcept
0326     {
0327         using namespace leaf_detail;
0328         BOOST_LEAF_ASSERT(!is_active());
0329         tuple_for_each<std::tuple_size<Tup>::value,Tup>::activate(tup_);
0330 #if BOOST_LEAF_CFG_DIAGNOSTICS
0331         if( unexpected_requested<Tup>::value )
0332             tls::uint_increment<tls_tag_unexpected_enabled_counter>();
0333 #endif
0334 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
0335         thread_id_ = std::this_thread::get_id();
0336 #endif
0337         is_active_ = true;
0338     }
0339 
0340     BOOST_LEAF_CONSTEXPR void deactivate() noexcept
0341     {
0342         using namespace leaf_detail;
0343         BOOST_LEAF_ASSERT(is_active());
0344         is_active_ = false;
0345 #if !defined(BOOST_LEAF_NO_THREADS) && !defined(NDEBUG)
0346         BOOST_LEAF_ASSERT(std::this_thread::get_id() == thread_id_);
0347         thread_id_ = std::thread::id();
0348 #endif
0349 #if BOOST_LEAF_CFG_DIAGNOSTICS
0350         if( unexpected_requested<Tup>::value )
0351             tls::uint_decrement<tls_tag_unexpected_enabled_counter>();
0352 #endif
0353         tuple_for_each<std::tuple_size<Tup>::value,Tup>::deactivate(tup_);
0354     }
0355 
0356     BOOST_LEAF_CONSTEXPR void propagate(error_id id) noexcept
0357     {
0358         BOOST_LEAF_ASSERT(!is_active());
0359         leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::propagate(tup_, id.value());
0360     }
0361 
0362     BOOST_LEAF_CONSTEXPR bool is_active() const noexcept
0363     {
0364         return is_active_;
0365     }
0366 
0367     template <class CharT, class Traits>
0368     void print( std::basic_ostream<CharT, Traits> & os ) const
0369     {
0370         leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::print(os, &tup_, 0);
0371     }
0372 
0373     template <class CharT, class Traits>
0374     friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, context const & ctx )
0375     {
0376         ctx.print(os);
0377         return os;
0378     }
0379 
0380     template <class R, class... H>
0381     BOOST_LEAF_CONSTEXPR R handle_error( error_id, H && ... ) const;
0382 
0383     template <class R, class... H>
0384     BOOST_LEAF_CONSTEXPR R handle_error( error_id, H && ... );
0385 };
0386 
0387 ////////////////////////////////////////
0388 
0389 namespace leaf_detail
0390 {
0391     template <class TypeList>
0392     struct deduce_context_impl;
0393 
0394     template <template <class...> class L, class... E>
0395     struct deduce_context_impl<L<E...>>
0396     {
0397         using type = context<E...>;
0398     };
0399 
0400     template <class TypeList>
0401     using deduce_context = typename deduce_context_impl<TypeList>::type;
0402 
0403     template <class H>
0404     struct fn_mp_args_fwd
0405     {
0406         using type = fn_mp_args<H>;
0407     };
0408 
0409     template <class... H>
0410     struct fn_mp_args_fwd<std::tuple<H...> &>: fn_mp_args_fwd<std::tuple<H...>> { };
0411 
0412     template <class... H>
0413     struct fn_mp_args_fwd<std::tuple<H...> const &>: fn_mp_args_fwd<std::tuple<H...>> { };
0414 
0415     template <class... H>
0416     struct fn_mp_args_fwd<std::tuple<H...>>
0417     {
0418         using type = leaf_detail_mp11::mp_append<typename fn_mp_args_fwd<H>::type...>;
0419     };
0420 
0421     template <class... H>
0422     struct context_type_from_handlers_impl
0423     {
0424         using type = deduce_context<leaf_detail_mp11::mp_append<typename fn_mp_args_fwd<H>::type...>>;
0425     };
0426 
0427     template <class Ctx>
0428     struct polymorphic_context_impl: polymorphic_context, Ctx
0429     {
0430         error_id propagate_captured_errors() noexcept final override { return Ctx::propagate_captured_errors(captured_id_); }
0431         void activate() noexcept final override { Ctx::activate(); }
0432         void deactivate() noexcept final override { Ctx::deactivate(); }
0433         void propagate(error_id id) noexcept final override { Ctx::propagate(id); }
0434         bool is_active() const noexcept final override { return Ctx::is_active(); }
0435 #if BOOST_LEAF_CFG_DIAGNOSTICS
0436         void print( std::ostream & os ) const final override { return Ctx::print(os); }
0437 #endif
0438     };
0439 }
0440 
0441 template <class... H>
0442 using context_type_from_handlers = typename leaf_detail::context_type_from_handlers_impl<H...>::type;
0443 
0444 ////////////////////////////////////////////
0445 
0446 template <class...  H>
0447 BOOST_LEAF_CONSTEXPR inline context_type_from_handlers<H...> make_context() noexcept
0448 {
0449     return { };
0450 }
0451 
0452 template <class...  H>
0453 BOOST_LEAF_CONSTEXPR inline context_type_from_handlers<H...> make_context( H && ... ) noexcept
0454 {
0455     return { };
0456 }
0457 
0458 ////////////////////////////////////////////
0459 
0460 #if BOOST_LEAF_CFG_CAPTURE
0461 
0462 template <class...  H>
0463 inline context_ptr make_shared_context() noexcept
0464 {
0465     return std::make_shared<leaf_detail::polymorphic_context_impl<context_type_from_handlers<H...>>>();
0466 }
0467 
0468 template <class...  H>
0469 inline context_ptr make_shared_context( H && ... ) noexcept
0470 {
0471     return std::make_shared<leaf_detail::polymorphic_context_impl<context_type_from_handlers<H...>>>();
0472 }
0473 
0474 #endif
0475 
0476 } }
0477 
0478 #endif