diff --git a/include/boost/fiber/future/detail/shared_state.hpp b/include/boost/fiber/future/detail/shared_state.hpp index 51891cc0..7a12559a 100644 --- a/include/boost/fiber/future/detail/shared_state.hpp +++ b/include/boost/fiber/future/detail/shared_state.hpp @@ -133,10 +133,6 @@ public: return wait_until_( lk, timeout_time); } - void reset() noexcept { - ready_ = false; - } - friend inline void intrusive_ptr_add_ref( shared_state_base * p) noexcept { ++p->use_count_; diff --git a/include/boost/fiber/future/detail/task_base.hpp b/include/boost/fiber/future/detail/task_base.hpp index 34af3d2a..907e8204 100644 --- a/include/boost/fiber/future/detail/task_base.hpp +++ b/include/boost/fiber/future/detail/task_base.hpp @@ -28,6 +28,8 @@ struct task_base : public shared_state< R > { } virtual void run( Args && ... args) = 0; + + virtual ptr_t reset() = 0; }; }}} diff --git a/include/boost/fiber/future/detail/task_object.hpp b/include/boost/fiber/future/detail/task_object.hpp index 999bcf96..fddac3ee 100644 --- a/include/boost/fiber/future/detail/task_object.hpp +++ b/include/boost/fiber/future/detail/task_object.hpp @@ -27,13 +27,16 @@ namespace detail { template< typename Fn, typename Allocator, typename R, typename ... Args > class task_object : public task_base< R, Args ... > { +private: + typedef task_base< R, Args ... > base_t; + public: typedef typename std::allocator_traits< Allocator >::template rebind_alloc< task_object > allocator_t; task_object( allocator_t const& alloc, Fn && fn) : - task_base< R, Args ... >(), + base_t(), fn_( std::move( fn) ), alloc_( alloc) { } @@ -48,6 +51,19 @@ public: } } + typename base_t::ptr_t reset() override final { + typedef std::allocator_traits< allocator_t > traits_t; + + typename traits_t::pointer ptr{ traits_t::allocate( alloc_, 1) }; + try { + traits_t::construct( alloc_, ptr, alloc_, std::move( fn_) ); + } catch (...) { + traits_t::deallocate( alloc_, ptr, 1); + throw; + } + return { convert( ptr) }; + } + protected: void deallocate_future() noexcept override final { destroy_( alloc_, this); @@ -65,13 +81,16 @@ private: template< typename Fn, typename Allocator, typename ... Args > class task_object< Fn, Allocator, void, Args ... > : public task_base< void, Args ... > { +private: + typedef task_base< void, Args ... > base_t; + public: typedef typename Allocator::template rebind< task_object< Fn, Allocator, void, Args ... > >::other allocator_t; task_object( allocator_t const& alloc, Fn && fn) : - task_base< void, Args ... >(), + base_t(), fn_( std::move( fn) ), alloc_( alloc) { } @@ -86,6 +105,19 @@ public: } } + typename base_t::ptr_t reset() override final { + typedef std::allocator_traits< allocator_t > traits_t; + + typename traits_t::pointer ptr{ traits_t::allocate( alloc_, 1) }; + try { + traits_t::construct( alloc_, ptr, alloc_, std::move( fn_) ); + } catch (...) { + traits_t::deallocate( alloc_, ptr, 1); + throw; + } + return { convert( ptr) }; + } + protected: void deallocate_future() noexcept override final { destroy_( alloc_, this); diff --git a/include/boost/fiber/future/packaged_task.hpp b/include/boost/fiber/future/packaged_task.hpp index 3fcc496d..857cec16 100644 --- a/include/boost/fiber/future/packaged_task.hpp +++ b/include/boost/fiber/future/packaged_task.hpp @@ -118,7 +118,10 @@ public: throw packaged_task_uninitialized{}; } obtained_ = false; - task_->reset(); + packaged_task tmp; + tmp.task_ = task_; + obtained_ = false; + task_ = tmp.task_->reset(); } };