Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:35

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_PACKAGED_TASK_HPP
0008 #define BOOST_FIBERS_PACKAGED_TASK_HPP
0009 
0010 #include <algorithm>
0011 #include <memory>
0012 #include <type_traits>
0013 #include <utility>
0014 
0015 #include <boost/config.hpp>
0016 
0017 #include <boost/fiber/detail/disable_overload.hpp>
0018 #include <boost/fiber/exceptions.hpp>
0019 #include <boost/fiber/future/detail/task_base.hpp>
0020 #include <boost/fiber/future/detail/task_object.hpp>
0021 #include <boost/fiber/future/future.hpp>
0022 
0023 namespace boost {
0024 namespace fibers {
0025 
0026 template< typename Signature >
0027 class packaged_task;
0028 
0029 template< typename R, typename ... Args >
0030 class packaged_task< R( Args ... ) > {
0031 private:
0032     typedef typename detail::task_base< R, Args ... >::ptr_type   ptr_type;
0033 
0034     bool            obtained_{ false };
0035     ptr_type        task_{};
0036 
0037 public:
0038     packaged_task() = default;
0039 
0040     template< typename Fn,
0041               typename = detail::disable_overload< packaged_task, Fn >
0042     >
0043     explicit packaged_task( Fn && fn) : 
0044         packaged_task{ std::allocator_arg,
0045                        std::allocator< packaged_task >{},
0046                        std::forward< Fn >( fn)  } {
0047     }
0048 
0049     template< typename Fn,
0050               typename Allocator
0051     >
0052     explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {
0053         typedef detail::task_object<
0054             typename std::decay< Fn >::type, Allocator, R, Args ...
0055         >                                       object_type;
0056         typedef std::allocator_traits<
0057             typename object_type::allocator_type
0058         >                                       traits_type;
0059         typedef pointer_traits< typename traits_type::pointer > ptrait_type;
0060 
0061         typename object_type::allocator_type a{ alloc };
0062         typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };
0063         typename ptrait_type::element_type* p = boost::to_address(ptr);
0064         try {
0065             traits_type::construct( a, p, a, std::forward< Fn >( fn) );
0066         } catch (...) {
0067             traits_type::deallocate( a, ptr, 1);
0068             throw;
0069         }
0070         task_.reset(p);
0071     }
0072 
0073     ~packaged_task() {
0074         if ( task_ && obtained_) {
0075             task_->owner_destroyed();
0076         }
0077     }
0078 
0079     packaged_task( packaged_task const&) = delete;
0080     packaged_task & operator=( packaged_task const&) = delete;
0081 
0082     packaged_task( packaged_task && other) noexcept :
0083         obtained_{ other.obtained_ },
0084         task_{ std::move( other.task_)  } {
0085         other.obtained_ = false;
0086     }
0087 
0088     packaged_task & operator=( packaged_task && other) noexcept {
0089         if ( BOOST_LIKELY( this != & other) ) {
0090             packaged_task tmp{ std::move( other) };
0091             swap( tmp);
0092         }
0093         return * this;
0094     }
0095 
0096     void swap( packaged_task & other) noexcept {
0097         std::swap( obtained_, other.obtained_);
0098         task_.swap( other.task_);
0099     }
0100 
0101     bool valid() const noexcept {
0102         return nullptr != task_.get();
0103     }
0104 
0105     future< R > get_future() {
0106         if ( obtained_) {
0107             throw future_already_retrieved{};
0108         }
0109         if ( BOOST_UNLIKELY( ! valid() ) ) {
0110             throw packaged_task_uninitialized{};
0111         }
0112         obtained_ = true;
0113         return future< R >{
0114              boost::static_pointer_cast< detail::shared_state< R > >( task_) };
0115     }
0116 
0117     void operator()( Args ... args) {
0118         if ( BOOST_UNLIKELY( ! valid() ) ) {
0119             throw packaged_task_uninitialized{};
0120         }
0121         task_->run( std::forward< Args >( args) ... );
0122     }
0123 
0124     void reset() {
0125         if ( BOOST_UNLIKELY( ! valid() ) ) {
0126             throw packaged_task_uninitialized{};
0127         }
0128         packaged_task tmp;
0129         tmp.task_ = task_;
0130         task_ = tmp.task_->reset();
0131         obtained_ = false;
0132     }
0133 };
0134 
0135 template< typename Signature >
0136 void swap( packaged_task< Signature > & l, packaged_task< Signature > & r) noexcept {
0137     l.swap( r);
0138 }
0139 
0140 }}
0141 
0142 #endif // BOOST_FIBERS_PACKAGED_TASK_HPP