| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 | 
//          Copyright Oliver Kowalke 2013.// Distributed under the Boost Software License, Version 1.0.//    (See accompanying file LICENSE_1_0.txt or copy at//          http://www.boost.org/LICENSE_1_0.txt)#ifndef BOOST_FIBERS_PACKAGED_TASK_HPP#define BOOST_FIBERS_PACKAGED_TASK_HPP#include <algorithm>#include <memory>#include <type_traits>#include <utility>#include <boost/config.hpp>#include <boost/fiber/detail/disable_overload.hpp>#include <boost/fiber/exceptions.hpp>#include <boost/fiber/future/detail/task_base.hpp>#include <boost/fiber/future/detail/task_object.hpp>#include <boost/fiber/future/future.hpp>namespace boost {namespace fibers {template< typename Signature >class packaged_task;template< typename R, typename ... Args >class packaged_task< R( Args ... ) > {private:    typedef typename detail::task_base< R, Args ... >::ptr_type   ptr_type;    bool            obtained_{ false };    ptr_type        task_{};public:    packaged_task() = default;    template< typename Fn,              typename = detail::disable_overload< packaged_task, Fn >    >    explicit packaged_task( Fn && fn) :         packaged_task{ std::allocator_arg,                       std::allocator< packaged_task >{},                       std::forward< Fn >( fn)  } {    }    template< typename Fn,              typename Allocator    >    explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) {        typedef detail::task_object<            typename std::decay< Fn >::type, Allocator, R, Args ...        >                                       object_type;        typedef std::allocator_traits<            typename object_type::allocator_type        >                                       traits_type;        typedef pointer_traits< typename traits_type::pointer > ptrait_type;        typename object_type::allocator_type a{ alloc };        typename traits_type::pointer ptr{ traits_type::allocate( a, 1) };        typename ptrait_type::element_type* p = boost::to_address(ptr);        try {            traits_type::construct( a, p, a, std::forward< Fn >( fn) );        } catch (...) {            traits_type::deallocate( a, ptr, 1);            throw;        }        task_.reset(p);    }    ~packaged_task() {        if ( task_ && obtained_) {            task_->owner_destroyed();        }    }    packaged_task( packaged_task const&) = delete;    packaged_task & operator=( packaged_task const&) = delete;    packaged_task( packaged_task && other) noexcept :        obtained_{ other.obtained_ },        task_{ std::move( other.task_)  } {        other.obtained_ = false;    }    packaged_task & operator=( packaged_task && other) noexcept {        if ( BOOST_LIKELY( this != & other) ) {            packaged_task tmp{ std::move( other) };            swap( tmp);        }        return * this;    }    void swap( packaged_task & other) noexcept {        std::swap( obtained_, other.obtained_);        task_.swap( other.task_);    }    bool valid() const noexcept {        return nullptr != task_.get();    }    future< R > get_future() {        if ( obtained_) {            throw future_already_retrieved{};        }        if ( BOOST_UNLIKELY( ! valid() ) ) {            throw packaged_task_uninitialized{};        }        obtained_ = true;        return future< R >{             boost::static_pointer_cast< detail::shared_state< R > >( task_) };    }    void operator()( Args ... args) {        if ( BOOST_UNLIKELY( ! valid() ) ) {            throw packaged_task_uninitialized{};        }        task_->run( std::forward< Args >( args) ... );    }    void reset() {        if ( BOOST_UNLIKELY( ! valid() ) ) {            throw packaged_task_uninitialized{};        }        packaged_task tmp;        tmp.task_ = task_;        task_ = tmp.task_->reset();        obtained_ = false;    }};template< typename Signature >void swap( packaged_task< Signature > & l, packaged_task< Signature > & r) noexcept {    l.swap( r);}}}#endif // BOOST_FIBERS_PACKAGED_TASK_HPP
 |