Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-31 09:37:22

0001 
0002 //          Copyright Oliver Kowalke 2013.
0003 // Distributed under the Boost Software License, Version 1.0.
0004 //    (See accompanying file LICENSE_1_0.txt or copy at
0005 //          http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 #ifndef BOOST_FIBERS_DETAIL_TASK_OBJECT_H
0008 #define BOOST_FIBERS_DETAIL_TASK_OBJECT_H
0009 
0010 #include <exception>
0011 #include <memory>
0012 #include <tuple>
0013 #include <utility>
0014 
0015 #include <boost/config.hpp>
0016 #include <boost/context/detail/config.hpp>
0017 #if defined(BOOST_NO_CXX17_STD_APPLY)
0018 #include <boost/context/detail/apply.hpp>
0019 #endif
0020 #include <boost/core/pointer_traits.hpp>
0021 
0022 #include <boost/fiber/detail/config.hpp>
0023 #include <boost/fiber/future/detail/task_base.hpp>
0024 
0025 #ifdef BOOST_HAS_ABI_HEADERS
0026 #  include BOOST_ABI_PREFIX
0027 #endif
0028 
0029 namespace boost {
0030 namespace fibers {
0031 namespace detail {
0032 
0033 template< typename Fn, typename Allocator, typename R, typename ... Args >
0034 class task_object : public task_base< R, Args ... > {
0035 private:
0036     typedef task_base< R, Args ... >    base_type;
0037     typedef std::allocator_traits< Allocator >  allocator_traits;
0038 
0039 public:
0040     typedef typename allocator_traits::template rebind_alloc<
0041         task_object
0042     >                                           allocator_type;
0043 
0044     task_object( allocator_type const& alloc, Fn const& fn) :
0045         base_type{},
0046         fn_{ fn },
0047         alloc_{ alloc } {
0048     }
0049 
0050     task_object( allocator_type const& alloc, Fn && fn) :
0051         base_type{},
0052         fn_{ std::move( fn) },
0053         alloc_{ alloc } {
0054     }
0055 
0056     void run( Args && ... args) override final {
0057         try {
0058             this->set_value(
0059 #if defined(BOOST_NO_CXX17_STD_APPLY)
0060                     boost::context::detail::apply(
0061                         fn_, std::make_tuple( std::forward< Args >( args) ... ) )
0062 #else
0063                     std::apply(
0064                         fn_, std::make_tuple( std::forward< Args >( args) ... ) )
0065 #endif
0066                     );
0067 #if defined(BOOST_CONTEXT_HAS_CXXABI_H)
0068         } catch ( abi::__forced_unwind const&) {
0069             throw;
0070 #endif
0071         } catch (...) {
0072             this->set_exception( std::current_exception() );
0073         }
0074     }
0075 
0076     typename base_type::ptr_type reset() override final {
0077         typedef std::allocator_traits< allocator_type >    traity_type;
0078         typedef pointer_traits< typename traity_type::pointer> ptrait_type;
0079 
0080         typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
0081         typename ptrait_type::element_type* p = boost::to_address(ptr);
0082         try {
0083             traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
0084         } catch (...) {
0085             traity_type::deallocate( alloc_, ptr, 1);
0086             throw;
0087         }
0088         return { p };
0089     }
0090 
0091 protected:
0092     void deallocate_future() noexcept override final {
0093         destroy_( alloc_, this);
0094     }
0095 
0096 private:
0097     Fn                  fn_;
0098     allocator_type      alloc_;
0099 
0100     static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
0101         allocator_type a{ alloc };
0102         typedef std::allocator_traits< allocator_type >    traity_type;
0103         traity_type::destroy( a, p);
0104         traity_type::deallocate( a, p, 1);
0105     }
0106 };
0107 
0108 template< typename Fn, typename Allocator, typename ... Args >
0109 class task_object< Fn, Allocator, void, Args ... > : public task_base< void, Args ... > {
0110 private:
0111     typedef task_base< void, Args ... >    base_type;
0112     typedef std::allocator_traits< Allocator >    allocator_traits;
0113 
0114 public:
0115     typedef typename allocator_traits::template rebind_alloc<
0116         task_object< Fn, Allocator, void, Args ... >
0117     >                                             allocator_type;
0118 
0119     task_object( allocator_type const& alloc, Fn const& fn) :
0120         base_type{},
0121         fn_{ fn },
0122         alloc_{ alloc } {
0123     }
0124 
0125     task_object( allocator_type const& alloc, Fn && fn) :
0126         base_type{},
0127         fn_{ std::move( fn) },
0128         alloc_{ alloc } {
0129     }
0130 
0131     void run( Args && ... args) override final {
0132         try {
0133 #if defined(BOOST_NO_CXX17_STD_APPLY)
0134             boost::context::detail::apply(
0135                     fn_, std::make_tuple( std::forward< Args >( args) ... ) );
0136 #else
0137             std::apply(
0138                     fn_, std::make_tuple( std::forward< Args >( args) ... ) );
0139 #endif
0140             this->set_value();
0141 #if defined(BOOST_CONTEXT_HAS_CXXABI_H)
0142         } catch ( abi::__forced_unwind const&) {
0143             throw;
0144 #endif
0145         } catch (...) {
0146             this->set_exception( std::current_exception() );
0147         }
0148     }
0149 
0150     typename base_type::ptr_type reset() override final {
0151         typedef std::allocator_traits< allocator_type >    traity_type;
0152         typedef pointer_traits< typename traity_type::pointer> ptrait_type;
0153 
0154         typename traity_type::pointer ptr{ traity_type::allocate( alloc_, 1) };
0155         typename ptrait_type::element_type* p = boost::to_address(ptr);
0156         try {
0157             traity_type::construct( alloc_, p, alloc_, std::move( fn_) );
0158         } catch (...) {
0159             traity_type::deallocate( alloc_, ptr, 1);
0160             throw;
0161         }
0162         return { p };
0163     }
0164 
0165 protected:
0166     void deallocate_future() noexcept override final {
0167         destroy_( alloc_, this);
0168     }
0169 
0170 private:
0171     Fn                  fn_;
0172     allocator_type      alloc_;
0173 
0174     static void destroy_( allocator_type const& alloc, task_object * p) noexcept {
0175         allocator_type a{ alloc };
0176         typedef std::allocator_traits< allocator_type >    traity_type;
0177         traity_type::destroy( a, p);
0178         traity_type::deallocate( a, p, 1);
0179     }
0180 };
0181 
0182 }}}
0183 
0184 #ifdef BOOST_HAS_ABI_HEADERS
0185 #  include BOOST_ABI_SUFFIX
0186 #endif
0187 
0188 #endif // BOOST_FIBERS_DETAIL_TASK_OBJECT_H