File indexing completed on 2025-01-31 09:37:22
0001
0002
0003
0004
0005
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