From 6d43540a29571c0f47f79368ed03e8057ab96a4b Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Tue, 15 Sep 2015 19:15:00 +0200 Subject: [PATCH] cleanup --- build/Jamfile.v2 | 14 +- include/boost/fiber/algorithm.hpp | 107 ---- include/boost/fiber/all.hpp | 15 - include/boost/fiber/barrier.hpp | 48 -- include/boost/fiber/bounded_channel.hpp | 417 ------------ include/boost/fiber/channel_op_status.hpp | 34 - include/boost/fiber/condition.hpp | 172 ----- include/boost/fiber/context.hpp | 372 +++++------ .../boost/fiber/detail/autoreset_event.hpp | 60 -- include/boost/fiber/detail/clock_cast.hpp | 42 -- include/boost/fiber/detail/fss.hpp | 62 -- .../boost/fiber/detail/interrupt_flags.hpp | 32 - include/boost/fiber/detail/invoke.hpp | 65 -- include/boost/fiber/detail/queues.hpp | 96 --- include/boost/fiber/detail/spinlock.hpp | 67 -- include/boost/fiber/exceptions.hpp | 262 -------- include/boost/fiber/fiber.hpp | 49 +- include/boost/fiber/fss.hpp | 112 ---- include/boost/fiber/future.hpp | 10 - include/boost/fiber/future/async.hpp | 48 -- .../fiber/future/detail/shared_state.hpp | 542 ---------------- .../future/detail/shared_state_object.hpp | 54 -- .../boost/fiber/future/detail/task_base.hpp | 39 -- .../boost/fiber/future/detail/task_object.hpp | 106 --- include/boost/fiber/future/future.hpp | 606 ------------------ include/boost/fiber/future/future_status.hpp | 25 - include/boost/fiber/future/packaged_task.hpp | 141 ---- include/boost/fiber/future/promise.hpp | 308 --------- include/boost/fiber/interruption.hpp | 68 -- include/boost/fiber/mutex.hpp | 61 -- include/boost/fiber/operations.hpp | 104 --- .../boost/fiber/posix/thread_local_ptr.hpp | 33 - include/boost/fiber/properties.hpp | 75 --- include/boost/fiber/recursive_mutex.hpp | 66 -- include/boost/fiber/recursive_timed_mutex.hpp | 82 --- include/boost/fiber/round_robin.hpp | 47 -- include/boost/fiber/scheduler.hpp | 51 +- include/boost/fiber/thread_local_ptr.hpp | 14 - include/boost/fiber/timed_mutex.hpp | 78 --- include/boost/fiber/unbounded_channel.hpp | 269 -------- .../boost/fiber/windows/thread_local_ptr.hpp | 42 -- src/algorithm.cpp | 34 - src/barrier.cpp | 54 -- src/condition.cpp | 64 -- src/context.cpp | 218 ++----- src/fiber.cpp | 55 +- src/future.cpp | 72 --- src/interruption.cpp | 70 -- src/mutex.cpp | 117 ---- src/properties.cpp | 39 -- src/recursive_mutex.cpp | 125 ---- src/recursive_timed_mutex.cpp | 164 ----- src/round_robin.cpp | 47 -- src/scheduler.cpp | 330 ++-------- src/timed_mutex.cpp | 156 ----- 55 files changed, 260 insertions(+), 6180 deletions(-) delete mode 100644 include/boost/fiber/algorithm.hpp delete mode 100644 include/boost/fiber/barrier.hpp delete mode 100644 include/boost/fiber/bounded_channel.hpp delete mode 100644 include/boost/fiber/channel_op_status.hpp delete mode 100644 include/boost/fiber/condition.hpp delete mode 100644 include/boost/fiber/detail/autoreset_event.hpp delete mode 100644 include/boost/fiber/detail/clock_cast.hpp delete mode 100644 include/boost/fiber/detail/fss.hpp delete mode 100644 include/boost/fiber/detail/interrupt_flags.hpp delete mode 100644 include/boost/fiber/detail/invoke.hpp delete mode 100644 include/boost/fiber/detail/queues.hpp delete mode 100644 include/boost/fiber/detail/spinlock.hpp delete mode 100644 include/boost/fiber/exceptions.hpp delete mode 100644 include/boost/fiber/fss.hpp delete mode 100644 include/boost/fiber/future.hpp delete mode 100644 include/boost/fiber/future/async.hpp delete mode 100644 include/boost/fiber/future/detail/shared_state.hpp delete mode 100644 include/boost/fiber/future/detail/shared_state_object.hpp delete mode 100644 include/boost/fiber/future/detail/task_base.hpp delete mode 100644 include/boost/fiber/future/detail/task_object.hpp delete mode 100644 include/boost/fiber/future/future.hpp delete mode 100644 include/boost/fiber/future/future_status.hpp delete mode 100644 include/boost/fiber/future/packaged_task.hpp delete mode 100644 include/boost/fiber/future/promise.hpp delete mode 100644 include/boost/fiber/interruption.hpp delete mode 100644 include/boost/fiber/mutex.hpp delete mode 100644 include/boost/fiber/operations.hpp delete mode 100644 include/boost/fiber/posix/thread_local_ptr.hpp delete mode 100644 include/boost/fiber/properties.hpp delete mode 100644 include/boost/fiber/recursive_mutex.hpp delete mode 100644 include/boost/fiber/recursive_timed_mutex.hpp delete mode 100644 include/boost/fiber/round_robin.hpp delete mode 100644 include/boost/fiber/thread_local_ptr.hpp delete mode 100644 include/boost/fiber/timed_mutex.hpp delete mode 100644 include/boost/fiber/unbounded_channel.hpp delete mode 100644 include/boost/fiber/windows/thread_local_ptr.hpp delete mode 100644 src/algorithm.cpp delete mode 100644 src/barrier.cpp delete mode 100644 src/condition.cpp delete mode 100644 src/future.cpp delete mode 100644 src/interruption.cpp delete mode 100644 src/mutex.cpp delete mode 100644 src/properties.cpp delete mode 100644 src/recursive_mutex.cpp delete mode 100644 src/recursive_timed_mutex.cpp delete mode 100644 src/round_robin.cpp delete mode 100644 src/timed_mutex.cpp diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index 7f055765..cf90355c 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -27,21 +27,9 @@ project boost/fiber ; lib boost_fiber - : algorithm.cpp - barrier.cpp - condition.cpp - context.cpp - detail/spinlock.cpp + : context.cpp fiber.cpp - future.cpp - interruption.cpp - mutex.cpp - properties.cpp - recursive_mutex.cpp - recursive_timed_mutex.cpp - round_robin.cpp scheduler.cpp - timed_mutex.cpp : shared:../../context/build//boost_context ; diff --git a/include/boost/fiber/algorithm.hpp b/include/boost/fiber/algorithm.hpp deleted file mode 100644 index 871219d0..00000000 --- a/include/boost/fiber/algorithm.hpp +++ /dev/null @@ -1,107 +0,0 @@ -// 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_ALGORITHM_H -#define BOOST_FIBERS_ALGORITHM_H - -#include - -#include -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class context; - -struct BOOST_FIBERS_DECL sched_algorithm { - virtual ~sched_algorithm() {} - - virtual void awakened( context *) = 0; - - virtual context * pick_next() = 0; - - virtual std::size_t ready_fibers() const noexcept = 0; -}; - -class BOOST_FIBERS_DECL sched_algorithm_with_properties_base : public sched_algorithm { -public: - // called by fiber_properties::notify() -- don't directly call - virtual void property_change_( context * f, fiber_properties * props) = 0; - -protected: - static fiber_properties* get_properties( context * f) noexcept; - static void set_properties( context * f, fiber_properties * p) noexcept; -}; - -template< typename PROPS > -struct sched_algorithm_with_properties : public sched_algorithm_with_properties_base { - typedef sched_algorithm_with_properties_base super; - - // Mark this override 'final': sched_algorithm_with_properties subclasses - // must override awakened() with properties parameter instead. Otherwise - // you'd have to remember to start every subclass awakened() override - // with: sched_algorithm_with_properties::awakened(fb); - virtual void awakened( context * f) final { - fiber_properties * props = super::get_properties( f); - if ( ! props) { - // TODO: would be great if PROPS could be allocated on the new - // fiber's stack somehow - props = new_properties( f); - // It is not good for new_properties() to return 0. - BOOST_ASSERT_MSG(props, "new_properties() must return non-NULL"); - // new_properties() must return instance of (a subclass of) PROPS - BOOST_ASSERT_MSG(dynamic_cast(props), - "new_properties() must return properties class"); - super::set_properties( f, props); - } - // Set sched_algo_ again every time this fiber becomes READY. That - // handles the case of a fiber migrating to a new thread with a new - // sched_algorithm subclass instance. - props->set_sched_algorithm( this); - - // Okay, now forward the call to subclass override. - awakened( f, properties(f) ); - } - - // subclasses override this method instead of the original awakened() - virtual void awakened( context *, PROPS& ) = 0; - - // used for all internal calls - PROPS& properties( context * f) { - return static_cast< PROPS & >( * super::get_properties( f) ); - } - - // override this to be notified by PROPS::notify() - virtual void property_change( context * f, PROPS & props) { - } - - // implementation for sched_algorithm_with_properties_base method - void property_change_( context * f, fiber_properties * props ) final { - property_change( f, * static_cast< PROPS * >( props) ); - } - - // Override this to customize instantiation of PROPS, e.g. use a different - // allocator. Each PROPS instance is associated with a particular - // context. - virtual fiber_properties * new_properties( context * f) { - return new PROPS( f); - } -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_ALGORITHM_H diff --git a/include/boost/fiber/all.hpp b/include/boost/fiber/all.hpp index 6dd47455..59bbcb0e 100644 --- a/include/boost/fiber/all.hpp +++ b/include/boost/fiber/all.hpp @@ -7,24 +7,9 @@ #ifndef BOOST_FIBERS_H #define BOOST_FIBERS_H -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include -#include #include -#include -#include -#include #include -#include -#include #endif // BOOST_FIBERS_H diff --git a/include/boost/fiber/barrier.hpp b/include/boost/fiber/barrier.hpp deleted file mode 100644 index a2a3044d..00000000 --- a/include/boost/fiber/barrier.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -// 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_BARRIER_H -#define BOOST_FIBERS_BARRIER_H - -#include - -#include - -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class BOOST_FIBERS_DECL barrier { -private: - std::size_t initial_; - std::size_t current_; - bool cycle_; - mutex mtx_; - condition cond_; - -public: - barrier( std::size_t); - - barrier( barrier const&) = delete; - barrier & operator=( barrier const&) = delete; - - bool wait(); -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_BARRIER_H diff --git a/include/boost/fiber/bounded_channel.hpp b/include/boost/fiber/bounded_channel.hpp deleted file mode 100644 index 2199f750..00000000 --- a/include/boost/fiber/bounded_channel.hpp +++ /dev/null @@ -1,417 +0,0 @@ - -// 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_BOUNDED_CHANNEL_H -#define BOOST_FIBERS_BOUNDED_CHANNEL_H - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -template< typename T, typename Allocator = std::allocator< T > > -class bounded_channel { -public: - typedef T value_type; - -private: - struct node { - typedef intrusive_ptr< node > ptr; - typedef typename std::allocator_traits< Allocator >::template rebind_alloc< node > allocator_type; - - std::size_t use_count; - allocator_type & alloc; - T va; - ptr nxt; - - explicit node( T const& t, allocator_type & alloc_) : - use_count( 0), - alloc( alloc_), - va( t), - nxt() { - } - - explicit node( T && t, allocator_type & alloc_) : - use_count( 0), - alloc( alloc_), - va( std::forward< T >( t) ), - nxt() { - } - - friend - void intrusive_ptr_add_ref( node * p) { - ++p->use_count; - } - - friend - void intrusive_ptr_release( node * p) { - if ( 0 == --p->use_count) { - allocator_type & alloc( p->alloc); - std::allocator_traits< allocator_type >::destroy( alloc, p); - std::allocator_traits< allocator_type >::deallocate( alloc, p, 1); - } - } - }; - - typedef typename std::allocator_traits< Allocator >::template rebind_alloc< node > allocator_type; - - enum class queue_status { - open = 0, - closed - }; - - allocator_type alloc_; - queue_status state_; - std::size_t count_; - typename node::ptr head_; - typename node::ptr * tail_; - mutable mutex mtx_; - condition not_empty_cond_; - condition not_full_cond_; - std::size_t hwm_; - std::size_t lwm_; - - bool is_closed_() const noexcept { - return queue_status::closed == state_; - } - - void close_( std::unique_lock< boost::fibers::mutex > & lk) { - state_ = queue_status::closed; - lk.unlock(); - not_empty_cond_.notify_all(); - not_full_cond_.notify_all(); - } - - std::size_t size_() const noexcept { - return count_; - } - - bool is_empty_() const noexcept { - return ! head_; - } - - bool is_full_() const noexcept { - return count_ >= hwm_; - } - - channel_op_status push_( typename node::ptr const& new_node, - std::unique_lock< boost::fibers::mutex > & lk) { - if ( is_closed_() ) { - return channel_op_status::closed; - } - - while ( is_full_() ) { - not_full_cond_.wait( lk); - } - - return push_and_notify_( new_node, lk); - } - - channel_op_status try_push_( typename node::ptr const& new_node, - std::unique_lock< boost::fibers::mutex > & lk) { - if ( is_closed_() ) { - return channel_op_status::closed; - } - - if ( is_full_() ) { - return channel_op_status::full; - } - - return push_and_notify_( new_node, lk); - } - - template< typename Clock, typename Duration > - channel_op_status push_wait_until_( typename node::ptr const& new_node, - std::chrono::time_point< Clock, Duration > const& timeout_time, - std::unique_lock< boost::fibers::mutex > & lk) { - if ( is_closed_() ) { - return channel_op_status::closed; - } - - while ( is_full_() ) { - if ( cv_status::timeout == not_full_cond_.wait_until( lk, timeout_time) ) { - return channel_op_status::timeout; - } - } - - return push_and_notify_( new_node, lk); - } - - channel_op_status push_and_notify_( typename node::ptr const& new_node, - std::unique_lock< boost::fibers::mutex > & lk) { - try { - push_tail_( new_node); - lk.unlock(); - not_empty_cond_.notify_one(); - - return channel_op_status::success; - } catch (...) { - close_( lk); - throw; - } - } - - void push_tail_( typename node::ptr new_node) { - * tail_ = new_node; - tail_ = & new_node->nxt; - ++count_; - } - - value_type value_pop_( std::unique_lock< boost::fibers::mutex > & lk) { - BOOST_ASSERT( ! is_empty_() ); - - try { - typename node::ptr old_head = pop_head_(); - if ( size_() <= lwm_) { - if ( lwm_ == hwm_) { - lk.unlock(); - not_full_cond_.notify_one(); - } else { - lk.unlock(); - // more than one producer could be waiting - // to push a value - not_full_cond_.notify_all(); - } - } - return std::move( old_head->va); - } catch (...) { - close_( lk); - throw; - } - } - - typename node::ptr pop_head_() { - typename node::ptr old_head = head_; - head_ = old_head->nxt; - if ( ! head_) { - tail_ = & head_; - } - old_head->nxt.reset(); - --count_; - return old_head; - } - -public: - bounded_channel( std::size_t hwm, - std::size_t lwm, - Allocator const& alloc = Allocator() ) : - alloc_( alloc), - state_( queue_status::open), - count_( 0), - head_(), - tail_( & head_), - mtx_(), - not_empty_cond_(), - not_full_cond_(), - hwm_( hwm), - lwm_( lwm) { - if ( hwm_ <= lwm_) { - throw invalid_argument( static_cast< int >( std::errc::invalid_argument), - "boost fiber: high-watermark is less than or equal to low-watermark for bounded_channel"); - } - if ( 0 == hwm) { - throw invalid_argument( static_cast< int >( std::errc::invalid_argument), - "boost fiber: high-watermark is zero"); - } - } - - bounded_channel( std::size_t wm, - Allocator const& alloc = Allocator() ) : - alloc_( alloc), - state_( queue_status::open), - count_( 0), - head_(), - tail_( & head_), - mtx_(), - not_empty_cond_(), - not_full_cond_(), - hwm_( wm), - lwm_() { - if ( 0 == wm) { - throw invalid_argument( static_cast< int >( std::errc::invalid_argument), - "boost fiber: watermark is zero"); - } - lwm_ = hwm_ - 1; - } - - bounded_channel( bounded_channel const&) = delete; - bounded_channel & operator=( bounded_channel const&) = delete; - - std::size_t upper_bound() const { - return hwm_; - } - - std::size_t lower_bound() const { - return lwm_; - } - - void close() { - std::unique_lock< mutex > lk( mtx_); - close_( lk); - } - - channel_op_status push( value_type const& va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( va, alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_( new_node, lk); - } - - channel_op_status push( value_type && va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( std::forward< value_type >( va), alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_( new_node, lk); - } - - template< typename Rep, typename Period > - channel_op_status push_wait_for( value_type const& va, - std::chrono::duration< Rep, Period > const& timeout_duration) { - return push_wait_until( va, - std::chrono::steady_clock::now() + timeout_duration); - } - - template< typename Rep, typename Period > - channel_op_status push_wait_for( value_type && va, - std::chrono::duration< Rep, Period > const& timeout_duration) { - return push_wait_until( std::forward< value_type >( va), - std::chrono::steady_clock::now() + timeout_duration); - } - - template< typename Clock, typename Duration > - channel_op_status push_wait_until( value_type const& va, - std::chrono::time_point< Clock, Duration > const& timeout_time) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( va, alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_wait_until_( new_node, timeout_time, lk); - } - - template< typename Clock, typename Duration > - channel_op_status push_wait_until( value_type && va, - std::chrono::time_point< Clock, Duration > const& timeout_time) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( std::forward< value_type >( va), alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_wait_until_( new_node, timeout_time, lk); - } - - channel_op_status try_push( value_type const& va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( va, alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return try_push_( new_node, lk); - } - - channel_op_status try_push( value_type && va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( std::forward< value_type >( va), alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return try_push_( new_node, lk); - } - - channel_op_status pop( value_type & va) { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - not_empty_cond_.wait( lk); - } - - if ( is_closed_() && is_empty_() ) { - return channel_op_status::closed; - } - - va = value_pop_( lk); - return channel_op_status::success; - } - - value_type value_pop() { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - not_empty_cond_.wait( lk); - } - - if ( is_closed_() && is_empty_() ) { - throw logic_error("boost fiber: queue is closed"); - } - - return value_pop_( lk); - } - - channel_op_status try_pop( value_type & va) { - std::unique_lock< mutex > lk( mtx_); - - if ( is_closed_() && is_empty_() ) { - // let other fibers run - lk.unlock(); - this_fiber::yield(); - return channel_op_status::closed; - } - - if ( is_empty_() ) { - // let other fibers run - lk.unlock(); - this_fiber::yield(); - return channel_op_status::empty; - } - - va = value_pop_( lk); - return channel_op_status::success; - } - - template< typename Rep, typename Period > - channel_op_status pop_wait_for( value_type & va, - std::chrono::duration< Rep, Period > const& timeout_duration) { - return pop_wait_until( va, - std::chrono::steady_clock::now() + timeout_duration); - } - - template< typename Clock, typename Duration > - channel_op_status pop_wait_until( value_type & va, - std::chrono::time_point< Clock, Duration > const& timeout_time) { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - if ( cv_status::timeout == not_empty_cond_.wait_until( lk, timeout_time) ) { - return channel_op_status::timeout; - } - } - - if ( is_closed_() && is_empty_() ) { - return channel_op_status::closed; - } - - va = value_pop_( lk); - return channel_op_status::success; - } -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_BOUNDED_CHANNEL_H diff --git a/include/boost/fiber/channel_op_status.hpp b/include/boost/fiber/channel_op_status.hpp deleted file mode 100644 index 78fd9bd6..00000000 --- a/include/boost/fiber/channel_op_status.hpp +++ /dev/null @@ -1,34 +0,0 @@ -// 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_QUEUE_OP_STATUS_H -#define BOOST_FIBERS_QUEUE_OP_STATUS_H - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -enum class channel_op_status { - success = 0, - empty, - full, - closed, - timeout -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_QUEUE_OP_STATUS_H diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp deleted file mode 100644 index 929499c4..00000000 --- a/include/boost/fiber/condition.hpp +++ /dev/null @@ -1,172 +0,0 @@ - -// 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_CONDITION_H -#define BOOST_FIBERS_CONDITION_H - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class context; - -enum class cv_status { - no_timeout = 1, - timeout -}; - -class BOOST_FIBERS_DECL condition { -private: - typedef detail::wait_queue< context > wait_queue_t; - - detail::spinlock splk_; - wait_queue_t wait_queue_; - -public: - condition(); - - ~condition(); - - condition( condition const&) = delete; - condition & operator=( condition const&) = delete; - - void notify_one(); - - void notify_all(); - - template< typename LockType, typename Pred > - void wait( LockType & lt, Pred pred) { - while ( ! pred() ) { - wait( lt); - } - } - - template< typename LockType > - void wait( LockType & lt) { - context * f( context::active() ); - try { - // lock spinlock - detail::spinlock_lock lk( splk_); - - // store this fiber in waiting-queue - // in order notify (resume) this fiber later - BOOST_ASSERT( ! f->wait_is_linked() ); - wait_queue_.push_back( * f); - lk.unlock(); - - // unlock external - lt.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - f->do_schedule(); - - // lock external again before returning - lt.lock(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } - - template< typename LockType, typename Clock, typename Duration > - cv_status wait_until( LockType & lt, std::chrono::time_point< Clock, Duration > const& timeout_time_) { - cv_status status = cv_status::no_timeout; - std::chrono::steady_clock::time_point timeout_time( - detail::clock_cast( timeout_time_) ); - context * f( context::active() ); - try { - // lock spinlock - detail::spinlock_lock lk( splk_); - - // store this fiber in waiting-queue - // in order notify (resume) this fiber later - BOOST_ASSERT( ! f->wait_is_linked() ); - wait_queue_.push_back( * f); - lk.unlock(); - - // unlock external - lt.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - if ( ! f->do_wait_until( timeout_time) ) { - // this fiber was not notified before timeout - // lock spinlock again - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - - status = cv_status::timeout; - } - - // lock external again before returning - lt.lock(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - - return status; - } - - template< typename LockType, typename Clock, typename Duration, typename Pred > - bool wait_until( LockType & lt, - std::chrono::time_point< Clock, Duration > const& timeout_time, Pred pred) { - while ( ! pred() ) { - if ( cv_status::timeout == wait_until( lt, timeout_time) ) { - return pred(); - } - } - return true; - } - - template< typename LockType, typename Rep, typename Period > - cv_status wait_for( LockType & lt, std::chrono::duration< Rep, Period > const& timeout_duration) { - return wait_until( lt, - std::chrono::steady_clock::now() + timeout_duration); - } - - template< typename LockType, typename Rep, typename Period, typename Pred > - bool wait_for( LockType & lt, std::chrono::duration< Rep, Period > const& timeout_duration, Pred pred) { - return wait_until( lt, - std::chrono::steady_clock::now() + timeout_duration, - pred); - } -}; - -typedef condition condition_variable; -typedef condition condition_variable_any; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_CONDITION_H diff --git a/include/boost/fiber/context.hpp b/include/boost/fiber/context.hpp index a5df3796..82b43ce1 100644 --- a/include/boost/fiber/context.hpp +++ b/include/boost/fiber/context.hpp @@ -7,29 +7,17 @@ #ifndef BOOST_FIBERS_CONTEXT_H #define BOOST_FIBERS_CONTEXT_H -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include #include -#include +#include +#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -38,14 +26,57 @@ namespace boost { namespace fibers { +class context; class fiber; -class fiber_properties; class scheduler; -struct sched_algorithm; + +namespace detail { + +struct wait_tag; +typedef intrusive::list_member_hook< + intrusive::tag< wait_tag >, + intrusive::link_mode< + intrusive::auto_unlink + > +> wait_hook; +// declaration of the functor that converts between +// the context class and the hook +struct wait_functor { + // required types + typedef wait_hook hook_type; + typedef hook_type * hook_ptr; + typedef const hook_type * const_hook_ptr; + typedef context value_type; + typedef value_type * pointer; + typedef const value_type * const_pointer; + + // required static functions + static hook_ptr to_hook_ptr( value_type &value); + static const_hook_ptr to_hook_ptr( value_type const& value); + static pointer to_value_ptr( hook_ptr n); + static const_pointer to_value_ptr( const_hook_ptr n); +}; + +struct ready_tag; +typedef intrusive::list_member_hook< + intrusive::tag< ready_tag >, + intrusive::link_mode< + intrusive::safe_link + > +> ready_hook; + +} class BOOST_FIBERS_DECL context { +public: + detail::wait_hook wait_hook_; + + typedef intrusive::list< context, + intrusive::function_hook< detail::wait_functor >, + intrusive::constant_time_size< false > > wait_queue_t; + private: - enum class fiber_status { + enum class status { ready = 0, running, waiting, @@ -53,56 +84,24 @@ private: }; enum flag_t { - flag_main_context = 1 << 1, - flag_interruption_blocked = 1 << 2, - flag_interruption_requested = 1 << 3, - flag_detached = 1 << 4 + flag_main_context = 1 << 1, + flag_dispatcher_context = 1 << 2 }; - struct BOOST_FIBERS_DECL fss_data { - void * vp; - detail::fss_cleanup_function::ptr_t cleanup_function; - - fss_data() : - vp( nullptr), - cleanup_function() { - } - - fss_data( void * vp_, - detail::fss_cleanup_function::ptr_t const& fn) : - vp( vp_), - cleanup_function( fn) { - BOOST_ASSERT( cleanup_function); - } - - void do_cleanup() { - ( * cleanup_function)( vp); - } - }; - - typedef std::map< uintptr_t, fss_data > fss_data_t; - typedef std::vector< context * > wait_queue_t; - //typedef detail::wait_queue< context > wait_queue_t; - - static thread_local context * active_; + static thread_local context * active_; #if ! defined(BOOST_FIBERS_NO_ATOMICS) - std::atomic< std::size_t > use_count_; - std::atomic< fiber_status > state_; - std::atomic< int > flags_; + std::atomic< std::size_t > use_count_; + std::atomic< status > state_; + std::atomic< int > flags_; #else - std::size_t use_count_; - fiber_status state_; - int flags_; + std::size_t use_count_; + status state_; + int flags_; #endif - detail::spinlock splk_; - scheduler * scheduler_; - boost::context::execution_context ctx_; - fss_data_t fss_data_; - wait_queue_t wait_queue_; - std::exception_ptr except_; - std::chrono::steady_clock::time_point tp_; - fiber_properties * properties_; + scheduler * scheduler_; + boost::context::execution_context ctx_; + wait_queue_t wait_queue_; protected: virtual void deallocate() { @@ -165,10 +164,7 @@ public: } }; - detail::runnable_hook runnable_hook_; detail::ready_hook ready_hook_; - detail::sleep_hook sleep_hook_; - detail::wait_hook wait_hook_; static context * active() noexcept; @@ -176,237 +172,125 @@ public: // main fiber context() : - use_count_( 1), // allocated on stack - state_( fiber_status::running), + use_count_( 1), // allocated on main- or thread-stack + state_( status::running), flags_( flag_main_context), - splk_(), scheduler_( nullptr), ctx_( boost::context::execution_context::current() ), - fss_data_(), wait_queue_(), - except_(), - tp_( (std::chrono::steady_clock::time_point::max)() ), - properties_( nullptr) { + ready_hook_() { } // worker fiber template< typename StackAlloc, typename Fn, typename ... Args > - context( boost::context::preallocated palloc, - StackAlloc salloc, - Fn && fn, - Args && ... args) : - use_count_( 1), // allocated on stack - state_( fiber_status::ready), + context( boost::context::preallocated palloc, StackAlloc salloc, + Fn && fn, Args && ... args) : + use_count_( 1), // allocated on fiber-stack + state_( status::ready), flags_( 0), - splk_(), scheduler_( nullptr), ctx_( palloc, salloc, // lambda, executed in execution context // mutable: generated operator() is not const -> enables std::move( fn) // std::make_tuple: stores decayed copies of its args, implicitly unwraps std::reference_wrapper [=,fn=std::forward< Fn >( fn),tpl=std::make_tuple( std::forward< Args >( args) ...)] () mutable -> void { - try { - BOOST_ASSERT( is_running() ); - detail::invoke_helper( std::move( fn), std::move( tpl) ); - BOOST_ASSERT( is_running() ); - } catch( fiber_interrupted const&) { - except_ = std::current_exception(); - } catch( ... ) { - std::terminate(); - } - + //FIXME: invoke function + // mark fiber as terminated set_terminated(); // notify waiting (joining) fibers release(); - // switch to another fiber - do_schedule(); + // FIXME: switch to another fiber BOOST_ASSERT_MSG( false, "fiber already terminated"); }), - fss_data_(), wait_queue_(), - except_(), - tp_( (std::chrono::steady_clock::time_point::max)() ), - properties_( nullptr) { + ready_hook_() { } virtual ~context(); - void set_scheduler( scheduler * mgr) { - BOOST_ASSERT( nullptr != mgr); - scheduler_ = mgr; - } + void set_scheduler( scheduler *); - scheduler * get_scheduler() const noexcept { - return scheduler_; - } + scheduler * get_scheduler() const noexcept; - id get_id() const noexcept { - return id( const_cast< context * >( this) ); - } - - bool join( context *); - - bool interruption_blocked() const noexcept { - return 0 != ( flags_ & flag_interruption_blocked); - } - - void interruption_blocked( bool blck) noexcept; - - bool interruption_requested() const noexcept { - return 0 != ( flags_ & flag_interruption_requested); - } - - void request_interruption( bool req) noexcept; + id get_id() const noexcept; bool is_main_context() const noexcept { return 0 != ( flags_ & flag_main_context); } bool is_terminated() const noexcept { - return fiber_status::terminated == state_; + return status::terminated == state_; } bool is_ready() const noexcept { - return fiber_status::ready == state_; + return status::ready == state_; } bool is_running() const noexcept { - return fiber_status::running == state_; + return status::running == state_; } bool is_waiting() const noexcept { - return fiber_status::waiting == state_; + return status::waiting == state_; } void set_terminated() noexcept { #if ! defined(BOOST_FIBERS_NO_ATOMICS) - fiber_status previous = state_.exchange( fiber_status::terminated); + status previous = state_.exchange( status::terminated); #else - fiber_status previous = state_; - state_ = fiber_status::terminated; + status previous = state_; + state_ = status::terminated; #endif - BOOST_ASSERT( fiber_status::running == previous); + BOOST_ASSERT( status::running == previous); (void)previous; } void set_ready() noexcept { #if ! defined(BOOST_FIBERS_NO_ATOMICS) - fiber_status previous = state_.exchange( fiber_status::ready); + status previous = state_.exchange( status::ready); #else - fiber_status previous = state_; - state_ = fiber_status::ready; + status previous = state_; + state_ = status::ready; #endif - BOOST_ASSERT( fiber_status::waiting == previous || fiber_status::running == previous || fiber_status::ready == previous); + BOOST_ASSERT( status::waiting == previous || status::running == previous || status::ready == previous); (void)previous; } void set_running() noexcept { #if ! defined(BOOST_FIBERS_NO_ATOMICS) - fiber_status previous = state_.exchange( fiber_status::running); + status previous = state_.exchange( status::running); #else - fiber_status previous = state_; - state_ = fiber_status::running; + status previous = state_; + state_ = status::running; #endif - BOOST_ASSERT( fiber_status::ready == previous); + BOOST_ASSERT( status::ready == previous); (void)previous; } void set_waiting() noexcept { #if ! defined(BOOST_FIBERS_NO_ATOMICS) - fiber_status previous = state_.exchange( fiber_status::waiting); + status previous = state_.exchange( status::waiting); #else - fiber_status previous = state_; - state_ = fiber_status::waiting; + status previous = state_; + state_ = status::waiting; #endif - BOOST_ASSERT( fiber_status::waiting == previous || fiber_status::running == previous); + BOOST_ASSERT( status::waiting == previous || status::running == previous); (void)previous; } - void * get_fss_data( void const * vp) const; + void resume(); - void set_fss_data( - void const * vp, - detail::fss_cleanup_function::ptr_t const& cleanup_fn, - void * data, - bool cleanup_existing); + void release() noexcept; - std::exception_ptr get_exception() const noexcept { - return except_; - } + bool wait_is_linked(); - void set_exception( std::exception_ptr except) noexcept { - except_ = except; - } + void wait_unlink(); - void resume() { - BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm - - ctx_(); - } - - std::chrono::steady_clock::time_point const& time_point() const noexcept { - return tp_; - } - - void time_point( std::chrono::steady_clock::time_point const& tp) { - tp_ = tp; - } - - void time_point_reset() { - tp_ = (std::chrono::steady_clock::time_point::max)(); - } - - void set_properties( fiber_properties* props); - - fiber_properties* get_properties() const { - return properties_; - } - - void release(); - - void do_spawn( fiber const&); - - void do_schedule(); - - bool do_wait_until( std::chrono::steady_clock::time_point const&); - - void do_yield(); - - void do_join( context *); - - void do_signal( context *); - - std::size_t do_ready_fibers() const noexcept; - - void do_set_sched_algo( std::unique_ptr< sched_algorithm >); - - bool runnable_is_linked() { - return runnable_hook_.is_linked(); - } - - bool ready_is_linked() { - return ready_hook_.is_linked(); - } - - bool sleep_is_linked() { - return sleep_hook_.is_linked(); - } - - void sleep_unlink() { - sleep_hook_.unlink(); - } - - bool wait_is_linked() { - return wait_hook_.is_linked(); - } - - void wait_unlink() { - wait_hook_.unlink(); - } + bool ready_is_linked(); friend void intrusive_ptr_add_ref( context * f) { BOOST_ASSERT( nullptr != f); @@ -422,7 +306,57 @@ public: } }; -}} +template< typename StackAlloc, typename Fn, typename ... Args > +static intrusive_ptr< context > make_context( StackAlloc salloc, Fn && fn, Args && ... args) { + boost::context::stack_context sctx( salloc.allocate() ); +#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN) + // reserve space for control structure + std::size_t size = sctx.size - sizeof( context); + void * sp = static_cast< char * >( sctx.sp) - sizeof( context); +#else + constexpr std::size_t func_alignment = 64; // alignof( context); + constexpr std::size_t func_size = sizeof( context); + // reserve space on stack + void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment; + // align sp pointer + std::size_t space = func_size + func_alignment; + sp = std::align( func_alignment, func_size, sp, space); + BOOST_ASSERT( nullptr != sp); + // calculate remaining size + std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) ); +#endif + // placement new of context on top of fiber's stack + return intrusive_ptr< context >( + new ( sp) context( + boost::context::preallocated( sp, size, sctx), + salloc, + std::forward< Fn >( fn), + std::forward< Args >( args) ... ) ); +} + +namespace detail { + +inline +wait_functor::hook_ptr wait_functor::to_hook_ptr( wait_functor::value_type & value) { + return & value.wait_hook_; +} + +inline +wait_functor::const_hook_ptr wait_functor::to_hook_ptr( wait_functor::value_type const& value) { + return & value.wait_hook_; +} + +inline +wait_functor::pointer wait_functor::to_value_ptr( wait_functor::hook_ptr n) { + return intrusive::get_parent_from_member< context >( n, & context::wait_hook_); +} + +inline +wait_functor::const_pointer wait_functor::to_value_ptr( wait_functor::const_hook_ptr n) { + return intrusive::get_parent_from_member< context >( n, & context::wait_hook_); +} + +}}} #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_SUFFIX diff --git a/include/boost/fiber/detail/autoreset_event.hpp b/include/boost/fiber/detail/autoreset_event.hpp deleted file mode 100644 index c83d4c91..00000000 --- a/include/boost/fiber/detail/autoreset_event.hpp +++ /dev/null @@ -1,60 +0,0 @@ - -// 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_DETAIL_AUTORESET_EVENT_H -#define BOOST_FIBERS_DETAIL_AUTORESET_EVENT_H - -#include -#include -#include - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -class autoreset_event { -private: - std::mutex mtx_; - std::condition_variable cnd_; - bool flag_; - -public: - autoreset_event() : - mtx_(), cnd_(), flag_( false) { - } - - autoreset_event( autoreset_event const&) = delete; - autoreset_event & operator=( autoreset_event const&) = delete; - - void set() { - std::unique_lock< std::mutex > lk( mtx_); - flag_ = true; - lk.unlock(); - cnd_.notify_all(); - } - - void reset( std::chrono::steady_clock::time_point const& time_point) { - std::unique_lock< std::mutex > lk( mtx_); - cnd_.wait_until( lk, time_point, [=](){ return flag_; }); - flag_ = false; - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_AUTORESET_EVENT_H diff --git a/include/boost/fiber/detail/clock_cast.hpp b/include/boost/fiber/detail/clock_cast.hpp deleted file mode 100644 index f7d78a6b..00000000 --- a/include/boost/fiber/detail/clock_cast.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -// 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_DETAIL_CLOCK_CAST_H -#define BOOST_FIBERS_DETAIL_CLOCK_CAST_H - -#include - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -inline -std::chrono::steady_clock::time_point clock_cast( - std::chrono::steady_clock::time_point const& timeout_time) noexcept { - return timeout_time; -} - -template< typename Clock, typename Duration > -std::chrono::steady_clock::time_point clock_cast( - std::chrono::time_point< Clock, Duration > const& timeout_time) { - return std::chrono::steady_clock::now() + ( timeout_time - Clock::now() ); -} - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_CLOCK_CAST_H diff --git a/include/boost/fiber/detail/fss.hpp b/include/boost/fiber/detail/fss.hpp deleted file mode 100644 index 2e072a7a..00000000 --- a/include/boost/fiber/detail/fss.hpp +++ /dev/null @@ -1,62 +0,0 @@ - -// 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) -// -// based on tss.hpp from boost.thread - -#ifndef BOOST_FIBERS_DETAIL_FSS_H -#define BOOST_FIBERS_DETAIL_FSS_H - -#include -#include - -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -class fss_cleanup_function { -private: - std::atomic< std::size_t > use_count_; - -public: - typedef intrusive_ptr< fss_cleanup_function > ptr_t; - - fss_cleanup_function() noexcept : - use_count_( 0) { - } - - virtual ~fss_cleanup_function() { - } - - virtual void operator()( void * data) = 0; - - friend inline - void intrusive_ptr_add_ref( fss_cleanup_function * p) noexcept { - ++p->use_count_; - } - - friend inline - void intrusive_ptr_release( fss_cleanup_function * p) { - if ( --p->use_count_ == 0) { - delete p; - } - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_FSS_H diff --git a/include/boost/fiber/detail/interrupt_flags.hpp b/include/boost/fiber/detail/interrupt_flags.hpp deleted file mode 100644 index 4ff945a8..00000000 --- a/include/boost/fiber/detail/interrupt_flags.hpp +++ /dev/null @@ -1,32 +0,0 @@ - -// 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_DETAIL_INTERRUPT_FLAGS_H -#define BOOST_FIBERS_DETAIL_INTERRUPT_FLAGS_H - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -enum interrupt_t { - INTERRUPTION_DISABLED = 1 << 1, - INTERRUPTION_ENABLED = 1 << 2, - INTERRUPTION_BLOCKED = 1 << 3 -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_INTERRUPT_FLAGS_H diff --git a/include/boost/fiber/detail/invoke.hpp b/include/boost/fiber/detail/invoke.hpp deleted file mode 100644 index 4b17f1ac..00000000 --- a/include/boost/fiber/detail/invoke.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -// Copyright Oliver Kowalke 2014. -// 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_DETAIL_INVOKE_H -#define BOOST_FIBERS_DETAIL_INVOKE_H - -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename Fn, typename... Args > -typename std::enable_if< - std::is_member_pointer< typename std::decay< Fn >::type >::value, - typename std::result_of< Fn&&( Args && ...) >::type ->::type -invoke_( Fn && fn, Args && ... args) { - return std::mem_fn( fn)( std::forward< Args >( args) ...); -} - -template< typename Fn, typename ... Args > -typename std::enable_if< - ! std::is_member_pointer< typename std::decay< Fn >::type >::value, - typename std::result_of< Fn&&( Args && ...) >::type ->::type -invoke_( Fn && fn, Args && ... args) { - return fn( std::forward< Args >( args) ...); -} - -template< typename Fn, typename Tpl, std::size_t... I > -decltype( auto) invoke_helper( Fn && fn, Tpl && tpl, std::index_sequence< I ... >) { - return invoke_( std::forward< Fn >( fn), - // std::tuple_element<> does not perfect forwarding - std::forward< decltype( std::get< I >( std::declval< Tpl >() ) ) >( - std::get< I >( std::forward< Tpl >( tpl) ) ) ... ); -} - - -template< typename Fn, typename Tpl > -decltype( auto) invoke_helper( Fn && fn, Tpl && tpl) { - constexpr auto Size = std::tuple_size< typename std::decay< Tpl >::type >::value; - return invoke_helper( std::forward< Fn >( fn), - std::forward< Tpl >( tpl), - std::make_index_sequence< Size >{}); -} - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -#include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_INVOKE_H diff --git a/include/boost/fiber/detail/queues.hpp b/include/boost/fiber/detail/queues.hpp deleted file mode 100644 index c09d3db9..00000000 --- a/include/boost/fiber/detail/queues.hpp +++ /dev/null @@ -1,96 +0,0 @@ - -// 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_DETAIL_QUEUES_H -#define BOOST_FIBERS_DETAIL_QUEUES_H - -#include -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -struct runnable_tag; -typedef intrusive::list_member_hook< - intrusive::tag< runnable_tag >, - intrusive::link_mode< - intrusive::safe_link - > -> runnable_hook; -template< typename T > -using runnable_queue = intrusive::list< - T, - intrusive::member_hook< T, runnable_hook, & T::runnable_hook_ > >; - -struct ready_tag; -typedef intrusive::list_member_hook< - intrusive::tag< ready_tag >, - intrusive::link_mode< - intrusive::safe_link - > -> ready_hook; -template< typename T > -using ready_queue = intrusive::list< - T, - intrusive::member_hook< T, ready_hook, & T::ready_hook_ >, - intrusive::constant_time_size< false > >; - -struct wait_tag; -typedef intrusive::list_member_hook< - intrusive::tag< wait_tag >, - intrusive::link_mode< - intrusive::auto_unlink - > -> wait_hook; -template< typename T > -using wait_queue = intrusive::list< - T, - intrusive::member_hook< T, wait_hook, & T::wait_hook_ >, - intrusive::constant_time_size< false > >; - -template< typename T > -struct timepoint_less { - bool operator()( T const& l, T const& r) { - return l.time_point() < r.time_point(); - } -}; - -struct sleep_tag; -typedef intrusive::set_member_hook< - intrusive::tag< sleep_tag >, - intrusive::link_mode< - intrusive::auto_unlink - > -> sleep_hook; -template< typename T > -using sleep_queue = intrusive::set< - T, - intrusive::member_hook< T, sleep_hook, & T::sleep_hook_ >, - intrusive::constant_time_size< false >, - intrusive::compare< timepoint_less< T > > >; - -template< typename T > -using remote_ready_queue = lockfree::queue< - T, - lockfree::fixed_sized< true >, - lockfree::capacity< 100 > >; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_QUEUES_H diff --git a/include/boost/fiber/detail/spinlock.hpp b/include/boost/fiber/detail/spinlock.hpp deleted file mode 100644 index 6e020010..00000000 --- a/include/boost/fiber/detail/spinlock.hpp +++ /dev/null @@ -1,67 +0,0 @@ - -// 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) -// -// based on boost::interprocess::sync::interprocess_spin::mutex - -#ifndef BOOST_FIBERS_SPINLOCK_H -#define BOOST_FIBERS_SPINLOCK_H - -#include -#include - -#include - -namespace boost { -namespace fibers { -namespace detail { - -class BOOST_FIBERS_DECL atomic_spinlock { -private: - enum class atomic_spinlock_status { - locked = 0, - unlocked - }; - - std::atomic< atomic_spinlock_status > state_; - -public: - atomic_spinlock() noexcept; - - atomic_spinlock( atomic_spinlock const&) = delete; - atomic_spinlock & operator=( atomic_spinlock const&) = delete; - - void lock(); - - void unlock() noexcept; -}; - -struct non_spinlock { - non_spinlock() noexcept {} - - void lock() {} - - void unlock() noexcept {} -}; - -struct non_lock { - non_lock( non_spinlock) {} - - void lock() {} - - void unlock() {} -}; - -#if ! defined(BOOST_FIBES_NO_ATOMICS) -typedef atomic_spinlock spinlock; -using spinlock_lock = std::unique_lock< spinlock >; -#else -typedef non_spinlock spinlock; -using spinlock_lock = non_lock; -#endif - -}}} - -#endif // BOOST_FIBERS_SPINLOCK_H diff --git a/include/boost/fiber/exceptions.hpp b/include/boost/fiber/exceptions.hpp deleted file mode 100644 index b02d68ae..00000000 --- a/include/boost/fiber/exceptions.hpp +++ /dev/null @@ -1,262 +0,0 @@ - -// 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) - -// based on boost.thread - -#ifndef BOOST_fiber_EXCEPTIONS_H -#define BOOST_fiber_EXCEPTIONS_H - -#include -#include -#include - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class fiber_exception : public std::system_error { -public: - fiber_exception() : - std::system_error( 0, std::system_category() ) { - } - - fiber_exception( int sys_error_code) : - std::system_error( sys_error_code, std::system_category() ) { - } - - fiber_exception( int ev, const char * what_arg) : - std::system_error( std::error_code( ev, std::system_category() ), what_arg) { - } - - fiber_exception( int ev, const std::string & what_arg) : - std::system_error( std::error_code( ev, std::system_category() ), what_arg) { - } - - virtual ~fiber_exception() throw() { - } -}; - -class condition_error : public fiber_exception { -public: - condition_error() : - fiber_exception( 0, "Condition error") { - } - - condition_error( int ev) : - fiber_exception( ev, "Condition error") { - } - - condition_error( int ev, const char * what_arg) : - fiber_exception( ev, what_arg) { - } - - condition_error( int ev, const std::string & what_arg) : - fiber_exception( ev, what_arg) { - } -}; - -class lock_error : public fiber_exception { -public: - lock_error() : - fiber_exception( 0, "boost::lock_error") { - } - - lock_error( int ev) : - fiber_exception( ev, "boost::lock_error") { - } - - lock_error( int ev, const char * what_arg) : - fiber_exception( ev, what_arg) { - } - - lock_error( int ev, const std::string & what_arg) : - fiber_exception( ev, what_arg) { - } -}; - -class fiber_resource_error : public fiber_exception { -public: - fiber_resource_error() : - fiber_exception( - static_cast< int >( std::errc::resource_unavailable_try_again), - "boost::fiber_resource_error") { - } - - fiber_resource_error( int ev) : - fiber_exception( ev, "boost::fiber_resource_error") { - } - - fiber_resource_error( int ev, const char * what_arg) : - fiber_exception( ev, what_arg) { - } - - fiber_resource_error( int ev, const std::string & what_arg) : - fiber_exception( ev, what_arg) { - } -}; - -class invalid_argument : public fiber_exception { -public: - invalid_argument() : - fiber_exception( - static_cast< int >( std::errc::invalid_argument), - "boost::invalid_argument") { - } - - invalid_argument( int ev) : - fiber_exception( ev, "boost::invalid_argument") { - } - - invalid_argument( int ev, const char * what_arg) : - fiber_exception( ev, what_arg) { - } - - invalid_argument( int ev, const std::string & what_arg) : - fiber_exception( ev, what_arg) { - } -}; - -class logic_error : public fiber_exception { -public: - logic_error() : - fiber_exception( 0, "boost::logic_error") { - } - - logic_error( const char * what_arg) : - fiber_exception( 0, what_arg) { - } - - logic_error( int ev) : - fiber_exception( ev, "boost::logic_error") { - } - - logic_error( int ev, const char * what_arg) : - fiber_exception( ev, what_arg) { - } - - logic_error( int ev, const std::string & what_arg) : - fiber_exception( ev, what_arg) { - } -}; - -class fiber_interrupted : public fiber_exception { -public: - fiber_interrupted() : - fiber_exception( - static_cast< int >( std::errc::interrupted), - "boost::fiber_interrupted") { - } -}; - -enum class future_errc { - unknown = 0, - broken_promise, - future_already_retrieved, - promise_already_satisfied, - no_state -}; - -BOOST_FIBERS_DECL -std::error_category const& future_category() noexcept; - -}} - -namespace std { - -template<> -struct is_error_code_enum< boost::fibers::future_errc > : public true_type { -}; - -inline -std::error_code make_error_code( boost::fibers::future_errc e) noexcept { - return std::error_code( static_cast< int >( e), boost::fibers::future_category() ); -} - -inline -std::error_condition make_error_condition( boost::fibers::future_errc e) noexcept { - return std::error_condition( static_cast< int >( e), boost::fibers::future_category() ); -} - -} - -namespace boost { -namespace fibers { - -class future_error : public std::logic_error { -private: - std::error_code ec_; - -public: - future_error( std::error_code ec) : - logic_error( ec.message() ), - ec_( ec) { - } - - std::error_code const& code() const noexcept { - return ec_; - } - - const char* what() const throw() { - return code().message().c_str(); - } -}; - -class future_uninitialized : public future_error { -public: - future_uninitialized() : - future_error( std::make_error_code( future_errc::no_state) ) { - } -}; - -class future_already_retrieved : public future_error { -public: - future_already_retrieved() : - future_error( std::make_error_code( future_errc::future_already_retrieved) ) { - } -}; - -class broken_promise : public future_error { -public: - broken_promise() : - future_error( std::make_error_code( future_errc::broken_promise) ) { - } -}; - -class promise_already_satisfied : public future_error { -public: - promise_already_satisfied() : - future_error( std::make_error_code( future_errc::promise_already_satisfied) ) { - } -}; - -class promise_uninitialized : public future_error { -public: - promise_uninitialized() : - future_error( std::make_error_code( future_errc::no_state) ) { - } -}; - -class packaged_task_uninitialized : public future_error { -public: - packaged_task_uninitialized() : - future_error( std::make_error_code( future_errc::no_state) ) { - } -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_fiber_EXCEPTIONS_H diff --git a/include/boost/fiber/fiber.hpp b/include/boost/fiber/fiber.hpp index f8cae57d..12d79dcd 100644 --- a/include/boost/fiber/fiber.hpp +++ b/include/boost/fiber/fiber.hpp @@ -10,12 +10,10 @@ #include #include #include -#include #include #include #include -#include #include #include @@ -29,8 +27,6 @@ namespace boost { namespace fibers { -class context; - class BOOST_FIBERS_DECL fiber { private: friend class context; @@ -41,34 +37,6 @@ private: void start_(); - template< typename StackAlloc, typename Fn, typename ... Args > - static ptr_t create( StackAlloc salloc, Fn && fn, Args && ... args) { - boost::context::stack_context sctx( salloc.allocate() ); -#if defined(BOOST_NO_CXX14_CONSTEXPR) || defined(BOOST_NO_CXX11_STD_ALIGN) - // reserve space for control structure - std::size_t size = sctx.size - sizeof( context); - void * sp = static_cast< char * >( sctx.sp) - sizeof( context); -#else - constexpr std::size_t func_alignment = 64; // alignof( context); - constexpr std::size_t func_size = sizeof( context); - // reserve space on stack - void * sp = static_cast< char * >( sctx.sp) - func_size - func_alignment; - // align sp pointer - std::size_t space = func_size + func_alignment; - sp = std::align( func_alignment, func_size, sp, space); - BOOST_ASSERT( nullptr != sp); - // calculate remaining size - std::size_t size = sctx.size - ( static_cast< char * >( sctx.sp) - static_cast< char * >( sp) ); -#endif - // placement new of context on top of fiber's stack - return ptr_t( - new ( sp) context( - boost::context::preallocated( sp, size, sctx), - salloc, - std::forward< Fn >( fn), - std::forward< Args >( args) ... ) ); - } - public: typedef context::id id; @@ -84,7 +52,7 @@ public: template< typename StackAllocator, typename Fn, typename ... Args > explicit fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) : - impl_( create( salloc, std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) { + impl_( make_context( salloc, std::forward< Fn >( fn), std::forward< Args >( args) ... ) ) { start_(); } @@ -125,25 +93,12 @@ public: } bool joinable() const noexcept { - return nullptr != impl_ /* && ! impl_->is_terminated() */; + return nullptr != impl_; } id get_id() const noexcept { return impl_ ? impl_->get_id() : id(); } - - void detach(); - - void join(); - - void interrupt() noexcept; - - template< typename PROPS > - PROPS & properties() { - fiber_properties* props = impl_->get_properties(); - BOOST_ASSERT_MSG(props, "fiber::properties not set"); - return dynamic_cast< PROPS & >( * props ); - } }; inline diff --git a/include/boost/fiber/fss.hpp b/include/boost/fiber/fss.hpp deleted file mode 100644 index b3f4c8f3..00000000 --- a/include/boost/fiber/fss.hpp +++ /dev/null @@ -1,112 +0,0 @@ - -// 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) -// -// based on tss.hpp from boost.thread - -#ifndef BOOST_FIBERS_FSS_H -#define BOOST_FIBERS_FSS_H - -#include - -#include -#include -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -template< typename T > -class fiber_specific_ptr { -private: - struct default_cleanup_function : public detail::fss_cleanup_function { - void operator()( void * data) { - delete static_cast< T * >( data); - } - }; - - struct custom_cleanup_function : public detail::fss_cleanup_function { - void (*fn)(T*); - - explicit custom_cleanup_function( void(*fn_)(T*) ): - fn( fn_) { - } - - void operator()( void* data) { - if ( fn) { - fn( static_cast< T * >( data) ); - } - } - }; - - detail::fss_cleanup_function::ptr_t cleanup_fn_; - -public: - typedef T element_type; - - fiber_specific_ptr() : - cleanup_fn_( new default_cleanup_function() ) { - } - - explicit fiber_specific_ptr( void(*fn)(T*) ) : - cleanup_fn_( new custom_cleanup_function( fn) ) { - } - - ~fiber_specific_ptr() { - context * f( context::active() ); - if ( nullptr != f) { - f->set_fss_data( - this, cleanup_fn_, nullptr, true); - } - } - - fiber_specific_ptr( fiber_specific_ptr const&) = delete; - fiber_specific_ptr & operator=( fiber_specific_ptr const&) = delete; - - T * get() const { - BOOST_ASSERT( context::active() ); - - void * vp( context::active()->get_fss_data( this) ); - return static_cast< T * >( vp); - } - - T * operator->() const { - return get(); - } - - T & operator*() const { - return * get(); - } - - T * release() { - T * tmp = get(); - context::active()->set_fss_data( - this, cleanup_fn_, nullptr, false); - return tmp; - } - - void reset( T * t) { - T * c = get(); - if ( c != t) { - context::active()->set_fss_data( - this, cleanup_fn_, t, true); - } - } -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_FSS_H diff --git a/include/boost/fiber/future.hpp b/include/boost/fiber/future.hpp deleted file mode 100644 index 2e5d3b77..00000000 --- a/include/boost/fiber/future.hpp +++ /dev/null @@ -1,10 +0,0 @@ - -// 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) - -#include -#include -#include -#include diff --git a/include/boost/fiber/future/async.hpp b/include/boost/fiber/future/async.hpp deleted file mode 100644 index 81bce336..00000000 --- a/include/boost/fiber/future/async.hpp +++ /dev/null @@ -1,48 +0,0 @@ - -// 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_ASYNC_HPP -#define BOOST_FIBERS_ASYNC_HPP - -#include // std::move() -#include // std::result_of -#include // std::forward() - -#include - -#include -#include - -namespace boost { -namespace fibers { - -template< typename Fn, typename ... Args > -future< typename std::result_of< Fn&&( Args && ... ) >::type > -async( Fn && fn, Args && ... args) { - typedef typename std::result_of< Fn&&( Args && ... ) >::type result_type; - - packaged_task< result_type( typename std::decay< Args >::type ... ) > pt( - std::forward< Fn >( fn) ); - future< result_type > f( pt.get_future() ); - fiber( std::move( pt), std::forward< Args >( args) ... ).detach(); - return std::move( f); -} - -template< typename StackAllocator, typename Fn, typename ... Args > -future< typename std::result_of< Fn&&( Args && ... ) >::type > -async( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args) { - typedef typename std::result_of< Fn&&( Args && ... ) >::type result_type; - - packaged_task< result_type( typename std::decay< Args >::type ... ) > pt( - std::forward< Fn >( fn) ); - future< result_type > f( pt.get_future() ); - fiber( salloc, std::move( pt), std::forward< Args >( args) ... ).detach(); - return std::move( f); -} - -}} - -#endif // BOOST_FIBERS_ASYNC_HPP diff --git a/include/boost/fiber/future/detail/shared_state.hpp b/include/boost/fiber/future/detail/shared_state.hpp deleted file mode 100644 index f0a6617a..00000000 --- a/include/boost/fiber/future/detail/shared_state.hpp +++ /dev/null @@ -1,542 +0,0 @@ - -// 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_DETAIL_SHARED_STATE_H -#define BOOST_FIBERS_DETAIL_SHARED_STATE_H - -#include // std::move() -#include -#include -#include -#include -#include // std::unique_lock - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename R > -class shared_state { -private: - std::atomic< std::size_t > use_count_; - mutable mutex mtx_; - mutable condition waiters_; - bool ready_; - optional< R > value_; - std::exception_ptr except_; - - void mark_ready_and_notify_( std::unique_lock< mutex > & lk) { - ready_ = true; - lk.unlock(); - waiters_.notify_all(); - } - - void owner_destroyed_( std::unique_lock< mutex > & lk) { - if ( ! ready_) { - set_exception_( - std::make_exception_ptr( broken_promise() ), - lk); - } - } - - void set_value_( R const& value, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - value_ = value; - mark_ready_and_notify_( lk); - } - - void set_value_( R && value, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - value_ = std::move( value); - mark_ready_and_notify_( lk); - } - - void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - except_ = except; - mark_ready_and_notify_( lk); - } - - R const& get_( std::unique_lock< mutex > & lk) { - wait_( lk); - if ( except_) { - std::rethrow_exception( except_); - } - return value_.get(); - } - - std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) { - wait_( lk); - return except_; - } - - void wait_( std::unique_lock< mutex > & lk) const { - while ( ! ready_) { - waiters_.wait( lk); - } - } - - template< class Rep, class Period > - future_status wait_for_( std::unique_lock< mutex > & lk, - std::chrono::duration< Rep, Period > const& timeout_duration) const { - while ( ! ready_) { - cv_status st( waiters_.wait_for( lk, timeout_duration) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - - template< typename Clock, typename Duration > - future_status wait_until_( std::unique_lock< mutex > & lk, - std::chrono::time_point< Clock, Duration > const& timeout_time) const { - while ( ! ready_) { - cv_status st( waiters_.wait_until( lk, timeout_time) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - -protected: - virtual void deallocate_future() = 0; - -public: - typedef intrusive_ptr< shared_state > ptr_t; - - shared_state() : - use_count_( 0), mtx_(), ready_( false), - value_(), except_() { - } - - virtual ~shared_state() noexcept { - } - - shared_state( shared_state const&) = delete; - shared_state & operator=( shared_state const&) = delete; - - void owner_destroyed() { - std::unique_lock< mutex > lk( mtx_); - owner_destroyed_( lk); - } - - void set_value( R const& value) { - std::unique_lock< mutex > lk( mtx_); - set_value_( value, lk); - } - - void set_value( R && value) { - std::unique_lock< mutex > lk( mtx_); - set_value_( std::move( value), lk); - } - - void set_exception( std::exception_ptr except) { - std::unique_lock< mutex > lk( mtx_); - set_exception_( except, lk); - } - - R const& get() { - std::unique_lock< mutex > lk( mtx_); - return get_( lk); - } - - std::exception_ptr get_exception_ptr() { - std::unique_lock< mutex > lk( mtx_); - return get_exception_ptr_( lk); - } - - void wait() const { - std::unique_lock< mutex > lk( mtx_); - wait_( lk); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - std::unique_lock< mutex > lk( mtx_); - return wait_for_( lk, timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - std::unique_lock< mutex > lk( mtx_); - return wait_until_( lk, timeout_time); - } - - void reset() { - ready_ = false; - } - - friend inline - void intrusive_ptr_add_ref( shared_state * p) noexcept { - ++p->use_count_; - } - - friend inline - void intrusive_ptr_release( shared_state * p) { - if ( 0 == --p->use_count_) { - p->deallocate_future(); - } - } -}; - -template< typename R > -class shared_state< R & > { -private: - std::atomic< std::size_t > use_count_; - mutable mutex mtx_; - mutable condition waiters_; - bool ready_; - R * value_; - std::exception_ptr except_; - - void mark_ready_and_notify_( std::unique_lock< mutex > & lk) { - ready_ = true; - lk.unlock(); - waiters_.notify_all(); - } - - void owner_destroyed_( std::unique_lock< mutex > & lk) { - if ( ! ready_) { - set_exception_( - std::make_exception_ptr( broken_promise() ), - lk); - } - } - - void set_value_( R & value, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - value_ = & value; - mark_ready_and_notify_( lk); - } - - void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - except_ = except; - mark_ready_and_notify_( lk); - } - - R & get_( std::unique_lock< mutex > & lk) { - wait_( lk); - if ( except_) { - std::rethrow_exception( except_); - } - return * value_; - } - - std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) { - wait_( lk); - return except_; - } - - void wait_( std::unique_lock< mutex > & lk) const { - while ( ! ready_) { - waiters_.wait( lk); - } - } - - template< class Rep, class Period > - future_status wait_for_( std::unique_lock< mutex > & lk, - std::chrono::duration< Rep, Period > const& timeout_duration) const { - while ( ! ready_) { - cv_status st( waiters_.wait_for( lk, timeout_duration) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - - template< typename Clock, typename Duration > - future_status wait_until_( std::unique_lock< mutex > & lk, - std::chrono::time_point< Clock, Duration > const& timeout_time) const { - while ( ! ready_) { - cv_status st( waiters_.wait_until( lk, timeout_time) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - -protected: - virtual void deallocate_future() = 0; - -public: - typedef intrusive_ptr< shared_state > ptr_t; - - shared_state() : - use_count_( 0), mtx_(), ready_( false), - value_( 0), except_() { - } - - virtual ~shared_state() noexcept { - } - - shared_state( shared_state const&) = delete; - shared_state & operator=( shared_state const&) = delete; - - void owner_destroyed() { - std::unique_lock< mutex > lk( mtx_); - owner_destroyed_( lk); - } - - void set_value( R & value) { - std::unique_lock< mutex > lk( mtx_); - set_value_( value, lk); - } - - void set_exception( std::exception_ptr except) { - std::unique_lock< mutex > lk( mtx_); - set_exception_( except, lk); - } - - R & get() { - std::unique_lock< mutex > lk( mtx_); - return get_( lk); - } - - std::exception_ptr get_exception_ptr() { - std::unique_lock< mutex > lk( mtx_); - return get_exception_ptr_( lk); - } - - void wait() const { - std::unique_lock< mutex > lk( mtx_); - wait_( lk); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - std::unique_lock< mutex > lk( mtx_); - return wait_for_( lk, timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - std::unique_lock< mutex > lk( mtx_); - return wait_until_( lk, timeout_time); - } - - void reset() { - ready_ = false; - } - - friend inline - void intrusive_ptr_add_ref( shared_state * p) noexcept { - ++p->use_count_; - } - - friend inline - void intrusive_ptr_release( shared_state * p) { - if ( 0 == --p->use_count_) { - p->deallocate_future(); - } - } -}; - -template<> -class shared_state< void > { -private: - std::atomic< std::size_t > use_count_; - mutable mutex mtx_; - mutable condition waiters_; - bool ready_; - std::exception_ptr except_; - - inline - void mark_ready_and_notify_( std::unique_lock< mutex > & lk) { - ready_ = true; - lk.unlock(); - waiters_.notify_all(); - } - - inline - void owner_destroyed_( std::unique_lock< mutex > & lk) { - if ( ! ready_) { - set_exception_( - std::make_exception_ptr( broken_promise() ), - lk); - } - } - - inline - void set_value_( std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - mark_ready_and_notify_( lk); - } - - inline - void set_exception_( std::exception_ptr except, std::unique_lock< mutex > & lk) { - if ( ready_) { - throw promise_already_satisfied(); - } - except_ = except; - mark_ready_and_notify_( lk); - } - - inline - void get_( std::unique_lock< mutex > & lk) { - wait_( lk); - if ( except_) { - std::rethrow_exception( except_); - } - } - - inline - std::exception_ptr get_exception_ptr_( std::unique_lock< mutex > & lk) { - wait_( lk); - return except_; - } - - inline - void wait_( std::unique_lock< mutex > & lk) const { - while ( ! ready_) { - waiters_.wait( lk); - } - } - - template< class Rep, class Period > - future_status wait_for_( std::unique_lock< mutex > & lk, - std::chrono::duration< Rep, Period > const& timeout_duration) const { - while ( ! ready_) { - cv_status st( waiters_.wait_for( lk, timeout_duration) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - - template< typename Clock, typename Duration > - future_status wait_until_( std::unique_lock< mutex > & lk, - std::chrono::time_point< Clock, Duration > const& timeout_time) const { - while ( ! ready_) { - cv_status st( waiters_.wait_until( lk, timeout_time) ); - if ( cv_status::timeout == st && ! ready_) { - return future_status::timeout; - } - } - return future_status::ready; - } - -protected: - virtual void deallocate_future() = 0; - -public: - typedef intrusive_ptr< shared_state > ptr_t; - - shared_state() : - use_count_( 0), mtx_(), ready_( false), except_() { - } - - virtual ~shared_state() noexcept { - } - - shared_state( shared_state const&) = delete; - shared_state & operator=( shared_state const&) = delete; - - inline - void owner_destroyed() { - std::unique_lock< mutex > lk( mtx_); - owner_destroyed_( lk); - } - - inline - void set_value() { - std::unique_lock< mutex > lk( mtx_); - set_value_( lk); - } - - inline - void set_exception( std::exception_ptr except) { - std::unique_lock< mutex > lk( mtx_); - set_exception_( except, lk); - } - - inline - void get() { - std::unique_lock< mutex > lk( mtx_); - get_( lk); - } - - inline - std::exception_ptr get_exception_ptr() { - std::unique_lock< mutex > lk( mtx_); - return get_exception_ptr_( lk); - } - - inline - void wait() const { - std::unique_lock< mutex > lk( mtx_); - wait_( lk); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - std::unique_lock< mutex > lk( mtx_); - return wait_for_( lk, timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - std::unique_lock< mutex > lk( mtx_); - return wait_until_( lk, timeout_time); - } - - inline - void reset() { - ready_ = false; - } - - friend inline - void intrusive_ptr_add_ref( shared_state * p) noexcept { - ++p->use_count_; - } - - friend inline - void intrusive_ptr_release( shared_state * p) { - if ( 0 == --p->use_count_) { - p->deallocate_future(); - } - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_SHARED_STATE_H diff --git a/include/boost/fiber/future/detail/shared_state_object.hpp b/include/boost/fiber/future/detail/shared_state_object.hpp deleted file mode 100644 index 8def4ed7..00000000 --- a/include/boost/fiber/future/detail/shared_state_object.hpp +++ /dev/null @@ -1,54 +0,0 @@ - -// 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_DETAIL_SHARED_STATE_OBJECT_H -#define BOOST_FIBERS_DETAIL_SHARED_STATE_OBJECT_H - -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename R, typename Allocator > -class shared_state_object : public shared_state< R > { -public: - typedef typename Allocator::template rebind< - shared_state_object< R, Allocator > - >::other allocator_t; - - shared_state_object( allocator_t const& alloc) : - shared_state< R >(), alloc_( alloc) { - } - -protected: - void deallocate_future() { - destroy_( alloc_, this); - } - -private: - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, shared_state_object * p) { - alloc.destroy( p); - alloc.deallocate( p, 1); - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_SHARED_STATE_OBJECT_H diff --git a/include/boost/fiber/future/detail/task_base.hpp b/include/boost/fiber/future/detail/task_base.hpp deleted file mode 100644 index a5692baa..00000000 --- a/include/boost/fiber/future/detail/task_base.hpp +++ /dev/null @@ -1,39 +0,0 @@ -// 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_DETAIL_TASK_BASE_H -#define BOOST_FIBERS_DETAIL_TASK_BASE_H - -#include -#include - -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename R, typename ... Args > -struct task_base : public shared_state< R > { - typedef intrusive_ptr< task_base > ptr_t; - - virtual ~task_base() noexcept { - } - - virtual void run( Args && ... args) = 0; -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_TASK_BASE_H diff --git a/include/boost/fiber/future/detail/task_object.hpp b/include/boost/fiber/future/detail/task_object.hpp deleted file mode 100644 index fbd2736f..00000000 --- a/include/boost/fiber/future/detail/task_object.hpp +++ /dev/null @@ -1,106 +0,0 @@ - -// 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_DETAIL_TASK_OBJECT_H -#define BOOST_FIBERS_DETAIL_TASK_OBJECT_H - -#include -#include // std::forward() - -#include - -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { -namespace detail { - -template< typename Fn, typename Allocator, typename R, typename ... Args > -class task_object : public task_base< R, Args ... > { -public: - typedef typename Allocator::template rebind< - task_object< Fn, Allocator, R, Args ... > - >::other allocator_t; - - explicit task_object( allocator_t const& alloc, Fn && fn) : - task_base< R, Args ... >(), - fn_( std::forward< Fn >( fn) ), - alloc_( alloc) { - } - - void run( Args && ... args) { - try { - this->set_value( invoke_helper( std::move( fn_), std::make_tuple( std::forward< Args >( args) ... ) ) ); - } catch (...) { - this->set_exception( std::current_exception() ); - } - } - -protected: - void deallocate_future() { - destroy_( alloc_, this); - } - -private: - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, task_object * p) { - alloc.destroy( p); - alloc.deallocate( p, 1); - } -}; - -template< typename Fn, typename Allocator, typename ... Args > -class task_object< Fn, Allocator, void, Args ... > : public task_base< void, Args ... > { -public: - typedef typename Allocator::template rebind< - task_object< Fn, Allocator, void, Args ... > - >::other allocator_t; - - explicit task_object( allocator_t const& alloc, Fn && fn) : - task_base< void, Args ... >(), - fn_( std::forward< Fn >( fn) ), - alloc_( alloc) { - } - - void run( Args && ... args) { - try { - invoke_helper( std::move( fn_), std::make_tuple( std::forward< Args >( args) ... ) ); - this->set_value(); - } catch (...) { - this->set_exception( std::current_exception() ); - } - } - -protected: - void deallocate_future() { - destroy_( alloc_, this); - } - -private: - Fn fn_; - allocator_t alloc_; - - static void destroy_( allocator_t & alloc, task_object * p) { - alloc.destroy( p); - alloc.deallocate( p, 1); - } -}; - -}}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DETAIL_TASK_OBJECT_H diff --git a/include/boost/fiber/future/future.hpp b/include/boost/fiber/future/future.hpp deleted file mode 100644 index 7dd9ef50..00000000 --- a/include/boost/fiber/future/future.hpp +++ /dev/null @@ -1,606 +0,0 @@ - -// 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_FUTURE_HPP -#define BOOST_FIBERS_FUTURE_HPP - -#include // std::move() -#include -#include - -#include - -#include -#include -#include -#include - -namespace boost { -namespace fibers { - -template< typename R > -class packaged_task; - -template< typename R > -class promise; - -template< typename R > -class shared_future; - -template< typename R > -class future { -private: - typedef typename detail::shared_state< R >::ptr_t ptr_t; - - friend class shared_future< R >; - - ptr_t state_; - -public: - future() noexcept : - state_() { - } - - explicit future( ptr_t const& p) noexcept : - state_( p) { - } - - ~future() noexcept { - } - - future( future const&) = delete; - future & operator=( future const&) = delete; - - future( future< R > && other) noexcept : - state_( std::move( other.state_) ) { - } - - future & operator=( future< R > && other) noexcept { - if ( this != & other) { - state_ = std::move( other.state_); - } - return * this; - } - - bool valid() const noexcept { - return nullptr != state_.get(); - } - - shared_future< R > share(); - - R get() { - if ( ! valid() ) { - throw future_uninitialized(); - } - ptr_t tmp; - tmp.swap( state_); - return tmp->get(); - } - - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - -template< typename R > -class future< R & > { -private: - typedef typename detail::shared_state< R & >::ptr_t ptr_t; - - friend class shared_future< R & >; - - ptr_t state_; - -public: - future() noexcept : - state_() { - } - - explicit future( ptr_t const& p) noexcept : - state_( p) { - } - - ~future() noexcept { - } - - future( future const&) = delete; - future & operator=( future const&) = delete; - - future( future< R & > && other) noexcept : - state_( std::move( other.state_) ) { - } - - future & operator=( future< R & > && other) noexcept { - if ( this != & other) { - state_ = std::move( other.state_); - } - return * this; - } - - bool valid() const noexcept { - return nullptr != state_.get(); - } - - shared_future< R & > share(); - - R & get() { - if ( ! valid() ) { - throw future_uninitialized(); - } - ptr_t tmp; - tmp.swap( state_); - return tmp->get(); - } - - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - -template<> -class future< void > { -private: - typedef detail::shared_state< void >::ptr_t ptr_t; - - friend class shared_future< void >; - - ptr_t state_; - -public: - future() noexcept : - state_() { - } - - explicit future( ptr_t const& p) noexcept : - state_( p) { - } - - ~future() noexcept { - } - - future( future const&) = delete; - future & operator=( future const&) = delete; - - inline - future( future< void > && other) noexcept : - state_( std::move( other.state_) ) { - } - - inline - future & operator=( future< void > && other) noexcept { - if ( this != & other) { - state_ = std::move( other.state_); - } - return * this; - } - - inline - bool valid() const noexcept { - return nullptr != state_.get(); - } - - shared_future< void > share(); - - inline - void get() { - if ( ! valid() ) { - throw future_uninitialized(); - } - ptr_t tmp; - tmp.swap( state_); - tmp->get(); - } - - inline - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - inline - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - - -template< typename R > -class shared_future { -private: - typedef typename detail::shared_state< R >::ptr_t ptr_t; - - friend class future< R >; - - ptr_t state_; - - explicit shared_future( ptr_t const& p) noexcept : - state_( p) { - } - -public: - shared_future() noexcept : - state_() { - } - - ~shared_future() noexcept { - } - - shared_future( shared_future const& other) : - state_( other.state_) { - } - - shared_future( shared_future && other) noexcept : - state_( std::move( other.state_) ) { - } - - shared_future( future< R > && other) noexcept : - state_( std::move( other.state_) ) { - } - - shared_future & operator=( shared_future const& other) noexcept { - if ( this != & other) { - state_ = other.state_; - } - return * this; - } - - shared_future & operator=( shared_future && other) noexcept { - if ( this != & other) { - state_= std::move( other.state_); - } - return * this; - } - - shared_future & operator=( future< R > && other) noexcept { - state_ = std::move( other.state_); - return * this; - } - - bool valid() const noexcept { - return nullptr != state_.get(); - } - - R const& get() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get(); - } - - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - -template< typename R > -class shared_future< R & > { -private: - typedef typename detail::shared_state< R & >::ptr_t ptr_t; - - friend class future< R & >; - - ptr_t state_; - - explicit shared_future( ptr_t const& p) noexcept : - state_( p) { - } - -public: - shared_future() noexcept : - state_() { - } - - ~shared_future() noexcept { - } - - shared_future( shared_future const& other) : - state_( other.state_) { - } - - shared_future( shared_future && other) noexcept : - state_( std::move( other.state_) ) { - } - - shared_future( future< R & > && other) noexcept : - state_( std::move( other.state_) ) { - } - - shared_future & operator=( shared_future const& other) noexcept { - if ( this != & other) { - state_ = other.state_; - } - return * this; - } - - shared_future & operator=( shared_future && other) noexcept { - if ( this != & other) { - state_ = std::move( other.state_); - } - return * this; - } - - shared_future & operator=( future< R & > && other) noexcept { - state_ = std::move( other.state_); - return * this; - } - - bool valid() const noexcept { - return nullptr != state_.get(); - } - - R & get() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get(); - } - - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - -template<> -class shared_future< void > { -private: - typedef detail::shared_state< void >::ptr_t ptr_t; - - friend class future< void >; - - ptr_t state_; - - shared_future( ptr_t const& p) noexcept : - state_( p) { - } - -public: - shared_future() noexcept : - state_() { - } - - ~shared_future() noexcept { - } - - inline - shared_future( shared_future const& other) : - state_( other.state_) { - } - - inline - shared_future( shared_future && other) noexcept : - state_( std::move( other.state_) ) { - } - - inline - shared_future( future< void > && other) noexcept : - state_( std::move( other.state_) ) { - } - - inline - shared_future & operator=( shared_future const& other) noexcept - { - if ( this != & other) { - state_ = other.state_; - } - return * this; - } - - inline - shared_future & operator=( shared_future && other) noexcept { - if ( this != & other) { - state_ = std::move( other.state_); - } - return * this; - } - - inline - shared_future & operator=( future< void > && other) noexcept { - state_ = std::move( other.state_); - return * this; - } - - inline - bool valid() const noexcept { - return nullptr != state_.get(); - } - - inline - void get() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->get(); - } - - inline - std::exception_ptr get_exception_ptr() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->get_exception_ptr(); - } - - inline - void wait() const { - if ( ! valid() ) { - throw future_uninitialized(); - } - state_->wait(); - } - - template< class Rep, class Period > - future_status wait_for( std::chrono::duration< Rep, Period > const& timeout_duration) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_for( timeout_duration); - } - - template< typename Clock, typename Duration > - future_status wait_until( std::chrono::time_point< Clock, Duration > const& timeout_time) const { - if ( ! valid() ) { - throw future_uninitialized(); - } - return state_->wait_until( timeout_time); - } -}; - - -template< typename R > -shared_future< R > -future< R >::share() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return shared_future< R >( std::move( * this) ); -} - -template< typename R > -shared_future< R & > -future< R & >::share() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return shared_future< R & >( std::move( * this) ); -} - -inline -shared_future< void > -future< void >::share() { - if ( ! valid() ) { - throw future_uninitialized(); - } - return shared_future< void >( std::move( * this) ); -} - -}} - -#endif diff --git a/include/boost/fiber/future/future_status.hpp b/include/boost/fiber/future/future_status.hpp deleted file mode 100644 index 351b73d0..00000000 --- a/include/boost/fiber/future/future_status.hpp +++ /dev/null @@ -1,25 +0,0 @@ - -// 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_FUTURE_STATUS_HPP -#define BOOST_FIBERS_FUTURE_STATUS_HPP - -#include - -#include - -namespace boost { -namespace fibers { - -enum class future_status { - ready = 1, - timeout, - deferred -}; - -}} - -#endif // BOOST_FIBERS_FUTURE_STATUS_HPP diff --git a/include/boost/fiber/future/packaged_task.hpp b/include/boost/fiber/future/packaged_task.hpp deleted file mode 100644 index 4725d34d..00000000 --- a/include/boost/fiber/future/packaged_task.hpp +++ /dev/null @@ -1,141 +0,0 @@ - -// 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 // std::move() -#include // std::allocator_arg -#include // std::forward() - -#include - -#include -#include -#include -#include - -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_t ptr_t; - - bool obtained_; - ptr_t task_; - -public: - packaged_task() noexcept : - obtained_( false), - task_() { - } - - ~packaged_task() { - if ( task_) { - task_->owner_destroyed(); - } - } - - template< typename Fn > - explicit packaged_task( Fn && fn) : - obtained_( false), - task_() { - typedef detail::task_object< - Fn, - std::allocator< packaged_task< R() > >, - R, - Args ... - > object_t; - std::allocator< packaged_task< R() > > alloc; - typename object_t::allocator_t a( alloc); - task_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a, std::forward< Fn >( fn) ) ); - } - - template< typename Fn, typename Allocator > - explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn) : - obtained_( false), - task_() { - typedef detail::task_object< - Fn, - Allocator, - R - > object_t; - typename object_t::allocator_t a( alloc); - task_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a, std::forward< Fn >( fn) ) ); - } - - 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 ( this != & other) { - obtained_ = other.obtained_; - other.obtained_ = false; - task_ = std::move( other.task_); - } - 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 ( ! valid() ) { - throw packaged_task_uninitialized(); - } - obtained_ = true; - return future< R >( - boost::static_pointer_cast< detail::shared_state< R > >( task_) ); - } - - void operator()( Args && ... args) { - if ( ! valid() ) { - throw packaged_task_uninitialized(); - } - task_->run( std::forward< Args >( args) ... ); - } - - void reset() { - if ( ! valid() ) { - throw packaged_task_uninitialized(); - } - obtained_ = false; - task_->reset(); - } -}; - -template< typename Signature > -void swap( packaged_task< Signature > & l, packaged_task< Signature > & r) { - l.swap( r); -} - -}} - -#endif // BOOST_FIBERS_PACKAGED_TASK_HPP diff --git a/include/boost/fiber/future/promise.hpp b/include/boost/fiber/future/promise.hpp deleted file mode 100644 index f0339552..00000000 --- a/include/boost/fiber/future/promise.hpp +++ /dev/null @@ -1,308 +0,0 @@ - -// 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_PROMISE_HPP -#define BOOST_FIBERS_PROMISE_HPP - -#include // std::move() -#include // std::allocator_arg -#include // std::forward() - -#include - -#include -#include -#include -#include - -namespace boost { -namespace fibers { - -template< typename R > -class promise { -private: - typedef typename detail::shared_state< R >::ptr_t ptr_t; - - bool obtained_; - ptr_t future_; - -public: - promise() : - obtained_( false), - future_() { - typedef detail::shared_state_object< - R, std::allocator< promise< R > > - > object_t; - std::allocator< promise< R > > alloc; - typename object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - template< typename Allocator > - promise( std::allocator_arg_t, Allocator alloc) : - obtained_( false), - future_() { - typedef detail::shared_state_object< R, Allocator > object_t; - typename object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - ~promise() { - if ( future_) { - future_->owner_destroyed(); - } - } - - promise( promise const&) = delete; - promise & operator=( promise const&) = delete; - - promise( promise && other) noexcept : - obtained_( other.obtained_), - future_( std::move( other.future_) ) { - other.obtained_ = false; - } - - promise & operator=( promise && other) noexcept { - if ( this != & other) { - obtained_ = other.obtained_; - other.obtained_ = false; - future_ = std::move( other.future_); - } - return * this; - } - - void swap( promise & other) noexcept { - std::swap( obtained_, other.obtained_); - future_.swap( other.future_); - } - - future< R > get_future() { - if ( obtained_) { - throw future_already_retrieved(); - } - if ( ! future_) { - throw promise_uninitialized(); - } - obtained_ = true; - return future< R >( future_); - } - - void set_value( R const& value) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_value( value); - } - - void set_value( R && value) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_value( std::move( value) ); - } - - void set_exception( std::exception_ptr p) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_exception( p); - } -}; - -template< typename R > -class promise< R & > { -private: - typedef typename detail::shared_state< R & >::ptr_t ptr_t; - - bool obtained_; - ptr_t future_; - -public: - promise() : - obtained_( false), - future_() { - typedef detail::shared_state_object< - R &, std::allocator< promise< R & > > - > object_t; - std::allocator< promise< R > > alloc; - typename object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - template< typename Allocator > - promise( std::allocator_arg_t, Allocator alloc) : - obtained_( false), - future_() { - typedef detail::shared_state_object< R &, Allocator > object_t; - typename object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - ~promise() { - if ( future_) { - future_->owner_destroyed(); - } - } - - promise( promise const&) = delete; - promise & operator=( promise const&) = delete; - - promise( promise && other) noexcept : - obtained_( other.obtained_), - future_( std::move( other.future_) ) { - other.obtained_ = false; - } - - promise & operator=( promise && other) noexcept { - if ( this != & other) { - obtained_ = other.obtained_; - other.obtained_ = false; - future_ = std::move( other.future_); - } - return * this; - } - - void swap( promise & other) noexcept { - std::swap( obtained_, other.obtained_); - future_.swap( other.future_); - } - - future< R & > get_future() { - if ( obtained_) { - throw future_already_retrieved(); - } - if ( ! future_) { - throw promise_uninitialized(); - } - obtained_ = true; - return future< R & >( future_); - } - - void set_value( R & value) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_value( value); - } - - void set_exception( std::exception_ptr p) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_exception( p); - } -}; - -template<> -class promise< void > { -private: - typedef detail::shared_state< void >::ptr_t ptr_t; - - bool obtained_; - ptr_t future_; - -public: - promise() : - obtained_( false), - future_() { - typedef detail::shared_state_object< - void, std::allocator< promise< void > > - > object_t; - std::allocator< promise< void > > alloc; - object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - template< typename Allocator > - promise( std::allocator_arg_t, Allocator alloc) : - obtained_( false), - future_() { - typedef detail::shared_state_object< void, Allocator > object_t; - typename object_t::allocator_t a( alloc); - future_ = ptr_t( - // placement new - ::new( a.allocate( 1) ) object_t( a) ); - } - - ~promise() { - if ( future_) { - future_->owner_destroyed(); - } - } - - promise( promise const&) = delete; - promise & operator=( promise const&) = delete; - - inline - promise( promise && other) noexcept : - obtained_( other.obtained_), - future_( std::move( other.future_) ) { - other.obtained_ = false; - } - - inline - promise & operator=( promise && other) noexcept { - if ( this != & other) { - obtained_ = other.obtained_; - other.obtained_ = false; - future_ = std::move( other.future_); - } - return * this; - } - - inline - void swap( promise & other) noexcept { - std::swap( obtained_, other.obtained_); - future_.swap( other.future_); - } - - inline - future< void > get_future() { - if ( obtained_) { - throw future_already_retrieved(); - } - if ( ! future_) { - throw promise_uninitialized(); - } - obtained_ = true; - return future< void >( future_); - } - - inline - void set_value() { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_value(); - } - - inline - void set_exception( std::exception_ptr p) { - if ( ! future_) { - throw promise_uninitialized(); - } - future_->set_exception( p); - } -}; - -template< typename R > -void swap( promise< R > & l, promise< R > & r) { - l.swap( r); -} - -}} - -#endif // BOOST_FIBERS_PROMISE_HPP diff --git a/include/boost/fiber/interruption.hpp b/include/boost/fiber/interruption.hpp deleted file mode 100644 index c9d42683..00000000 --- a/include/boost/fiber/interruption.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -// 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) -// -// based on boost.thread - -#ifndef BOOST_THIS_FIBER_INTERRUPTION_H -#define BOOST_THIS_FIBER_INTERRUPTION_H - -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace this_fiber { - -class restore_interruption; - -class BOOST_FIBERS_DECL disable_interruption { -private: - friend class restore_interruption; - - bool set_; - -public: - disable_interruption() noexcept; - - ~disable_interruption() noexcept; - - disable_interruption( disable_interruption const&) = delete; - disable_interruption & operator=( disable_interruption const&) = delete; -}; - -class BOOST_FIBERS_DECL restore_interruption { -private: - disable_interruption & disabler_; - -public: - explicit restore_interruption( disable_interruption & disabler) noexcept; - - ~restore_interruption() noexcept; - - restore_interruption( restore_interruption const&) = delete; - restore_interruption & operator=( restore_interruption const&) = delete; -}; - -BOOST_FIBERS_DECL -bool interruption_enabled() noexcept; - -BOOST_FIBERS_DECL -bool interruption_requested() noexcept; - -BOOST_FIBERS_DECL -void interruption_point(); - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_THIS_FIBER_INTERRUPTION_H diff --git a/include/boost/fiber/mutex.hpp b/include/boost/fiber/mutex.hpp deleted file mode 100644 index 95d8e17a..00000000 --- a/include/boost/fiber/mutex.hpp +++ /dev/null @@ -1,61 +0,0 @@ - -// 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_MUTEX_H -#define BOOST_FIBERS_MUTEX_H - -#include - -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class BOOST_FIBERS_DECL mutex { -private: - enum class mutex_status { - locked = 0, - unlocked - }; - - typedef detail::wait_queue< context > wait_queue_t; - - detail::spinlock splk_; - mutex_status state_; - context::id owner_; - wait_queue_t wait_queue_; - - bool lock_if_unlocked_(); - -public: - mutex(); - - ~mutex(); - - mutex( mutex const&) = delete; - mutex & operator=( mutex const&) = delete; - - void lock(); - - bool try_lock(); - - void unlock(); -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_MUTEX_H diff --git a/include/boost/fiber/operations.hpp b/include/boost/fiber/operations.hpp deleted file mode 100644 index 45567675..00000000 --- a/include/boost/fiber/operations.hpp +++ /dev/null @@ -1,104 +0,0 @@ -// 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_THIS_FIBER_OPERATIONS_H -#define BOOST_THIS_FIBER_OPERATIONS_H - -#include -#include -#include -#include // std::unique_lock - -#include -#include - -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace this_fiber { - -inline -fibers::fiber::id get_id() noexcept { - return fibers::context::active()->get_id(); -} - -inline -void yield() { - fibers::context::active()->do_yield(); -} - -template< typename Clock, typename Duration > -void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time_) { - std::chrono::steady_clock::time_point sleep_time( - boost::fibers::detail::clock_cast( sleep_time_) ); - fibers::context::active()->do_wait_until( sleep_time); - // check if fiber was interrupted - interruption_point(); -} - -template< typename Rep, typename Period > -void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration) { - fibers::context::active()->do_wait_until( - std::chrono::steady_clock::now() + timeout_duration); - // check if fiber was interrupted - interruption_point(); -} - -template< typename PROPS > -PROPS & properties() { - fibers::fiber_properties * props = - fibers::context::active()->get_properties(); - if ( ! props) { - // props could be nullptr if the thread's main fiber has not yet - // yielded (not yet passed through sched_algorithm_with_properties:: - // awakened()). Address that by yielding right now. - yield(); - // Try again to obtain the fiber_properties subclass instance ptr. - // Walk through the whole chain again because who knows WHAT might - // have happened while we were yielding! - props = fibers::context::active()->get_properties(); - // Could still be hosed if the running manager isn't a subclass of - // sched_algorithm_with_properties. - BOOST_ASSERT_MSG(props, "this_fiber::properties not set"); - } - return dynamic_cast< PROPS & >( * props ); -} - -} // this_fiber - -namespace fibers { - -inline -void migrate( fiber const& f) { - context::active()->do_spawn( f); -} - -inline -std::size_t ready_fibers() { - return context::active()->do_ready_fibers(); -} - -template< typename SchedAlgo, typename ... Args > -void use_scheduling_algorithm( Args && ... args) { - context::active()->do_set_sched_algo( - std::make_unique< SchedAlgo >( std::forward< Args >( args) ... ) ); -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_THIS_FIBER_OPERATIONS_H diff --git a/include/boost/fiber/posix/thread_local_ptr.hpp b/include/boost/fiber/posix/thread_local_ptr.hpp deleted file mode 100644 index 0d9306ab..00000000 --- a/include/boost/fiber/posix/thread_local_ptr.hpp +++ /dev/null @@ -1,33 +0,0 @@ - -// 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_THREAD_LOCAL_PTR_H -#define BOOST_FIBERS_THREAD_LOCAL_PTR_H - -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -template< typename T > -struct thread_local_ptr : public boost::thread_specific_ptr< T > -{}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_THREAD_LOCAL_PTR_H diff --git a/include/boost/fiber/properties.hpp b/include/boost/fiber/properties.hpp deleted file mode 100644 index a5b41dc5..00000000 --- a/include/boost/fiber/properties.hpp +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright Nat Goodspeed 2014. -// 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) - -// Define fiber_properties, a base class from which a library consumer can -// derive a subclass with specific properties important to a user-coded -// scheduler. - -#ifndef BOOST_FIBERS_PROPERTIES_HPP -#define BOOST_FIBERS_PROPERTIES_HPP - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -# if defined(BOOST_MSVC) -# pragma warning(push) -# pragma warning(disable:4275) -# endif - -namespace boost { -namespace fibers { - -struct sched_algorithm; -class context; - -class BOOST_FIBERS_DECL fiber_properties { -protected: - // initialized by constructor - context * fiber_; - // set every time this fiber becomes READY - sched_algorithm * sched_algo_; - - // Inform the relevant sched_algorithm instance that something important - // has changed, so it can (presumably) adjust its data structures - // accordingly. - void notify(); - -public: - // Any specific property setter method, after updating the relevant - // instance variable, can/should call notify(). - - // fiber_properties, and by implication every subclass, must accept a back - // pointer to its context. - fiber_properties( context* f): - fiber_( f), - sched_algo_( nullptr) { - } - - // We need a virtual destructor (hence a vtable) because fiber_properties - // is stored polymorphically (as fiber_properties*) in context, and - // destroyed via that pointer. - virtual ~fiber_properties() {} - - // not really intended for public use, but sched_algorithm_with_properties - // must be able to call this - void set_sched_algorithm( sched_algorithm * algo) { - sched_algo_ = algo; - } -}; - -}} // namespace boost::fibers - -# if defined(BOOST_MSVC) -# pragma warning(pop) -# endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_PROPERTIES_HPP diff --git a/include/boost/fiber/recursive_mutex.hpp b/include/boost/fiber/recursive_mutex.hpp deleted file mode 100644 index 39228b96..00000000 --- a/include/boost/fiber/recursive_mutex.hpp +++ /dev/null @@ -1,66 +0,0 @@ - -// 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) -// -// based on boost::interprocess::sync::interprocess_spinlock - -#ifndef BOOST_FIBERS_RECURSIVE_MUTEX_H -#define BOOST_FIBERS_RECURSIVE_MUTEX_H - -#include - -#include - -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class BOOST_FIBERS_DECL recursive_mutex { -private: - enum class mutex_status { - locked = 0, - unlocked - }; - - typedef detail::wait_queue< context > wait_queue_t; - - detail::spinlock splk_; - mutex_status state_; - context::id owner_; - std::size_t count_; - wait_queue_t wait_queue_; - - bool lock_if_unlocked_(); - -public: - recursive_mutex(); - - ~recursive_mutex(); - - recursive_mutex( recursive_mutex const&) = delete; - recursive_mutex & operator=( recursive_mutex const&) = delete; - - void lock(); - - bool try_lock(); - - void unlock(); -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_RECURSIVE_MUTEX_H diff --git a/include/boost/fiber/recursive_timed_mutex.hpp b/include/boost/fiber/recursive_timed_mutex.hpp deleted file mode 100644 index 71217476..00000000 --- a/include/boost/fiber/recursive_timed_mutex.hpp +++ /dev/null @@ -1,82 +0,0 @@ - -// 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) -// -// based on boost::interprocess::sync::interprocess_spinlock - -#ifndef BOOST_FIBERS_RECURSIVE_TIMED_MUTEX_H -#define BOOST_FIBERS_RECURSIVE_TIMED_MUTEX_H - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class BOOST_FIBERS_DECL recursive_timed_mutex { -private: - enum class mutex_status { - locked = 0, - unlocked - }; - - typedef detail::wait_queue< context > wait_queue_t; - - detail::spinlock splk_; - mutex_status state_; - context::id owner_; - std::size_t count_; - wait_queue_t wait_queue_; - - bool lock_if_unlocked_(); - - bool try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time); - -public: - recursive_timed_mutex(); - - ~recursive_timed_mutex(); - - recursive_timed_mutex( recursive_timed_mutex const&) = delete; - recursive_timed_mutex & operator=( recursive_timed_mutex const&) = delete; - - void lock(); - - bool try_lock(); - - template< typename Clock, typename Duration > - bool try_lock_until( std::chrono::time_point< Clock, Duration > const& timeout_time_) { - std::chrono::steady_clock::time_point timeout_time( - detail::clock_cast( timeout_time_) ); - return try_lock_until_( timeout_time); - } - - template< typename Rep, typename Period > - bool try_lock_for( std::chrono::duration< Rep, Period > const& timeout_duration) { - return try_lock_until_( std::chrono::steady_clock::now() + timeout_duration); - } - - void unlock(); -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_RECURSIVE_TIMED_MUTEX_H diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp deleted file mode 100644 index 672f09b1..00000000 --- a/include/boost/fiber/round_robin.hpp +++ /dev/null @@ -1,47 +0,0 @@ -// 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_DEFAULT_ROUND_ROBIN_H -#define BOOST_FIBERS_DEFAULT_ROUND_ROBIN_H - -#include - -#include - -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class context; - -class BOOST_FIBERS_DECL round_robin : public sched_algorithm { -private: - typedef detail::runnable_queue< context > runnable_queue_t; - - runnable_queue_t runnable_queue_; - -public: - virtual void awakened( context *); - - virtual context * pick_next(); - - virtual std::size_t ready_fibers() const noexcept; -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_DEFAULT_ROUND_ROBIN_H diff --git a/include/boost/fiber/scheduler.hpp b/include/boost/fiber/scheduler.hpp index 1af198b9..5c2e96e5 100644 --- a/include/boost/fiber/scheduler.hpp +++ b/include/boost/fiber/scheduler.hpp @@ -6,20 +6,12 @@ #ifndef BOOST_FIBERS_FIBER_MANAGER_H #define BOOST_FIBERS_FIBER_MANAGER_H -#include -#include -#include -#include - -#include #include +#include +#include #include -#include #include -#include -#include -#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -29,49 +21,34 @@ namespace boost { namespace fibers { class context; -struct sched_algorithm; class BOOST_FIBERS_DECL scheduler { private: - typedef detail::ready_queue< context > ready_queue_t; - typedef detail::sleep_queue< context > sleep_queue_t; - typedef std::vector< context * > terminated_queue_t; - typedef detail::remote_ready_queue< context * > remote_ready_queue_t; + typedef intrusive::list< + context, + intrusive::member_hook< + context, detail::ready_hook, & context::ready_hook_ >, + intrusive::constant_time_size< false > > ready_queue_t; - detail::autoreset_event ev_; - std::unique_ptr< sched_algorithm > sched_algo_; - context * main_context_; - ready_queue_t ready_queue_; - sleep_queue_t sleep_queue_; - terminated_queue_t terminated_queue_; - remote_ready_queue_t remote_ready_queue_; + context * main_ctx_; + intrusive_ptr< context > dispatching_ctx_; + ready_queue_t ready_queue_; void resume_( context *, context *); public: - scheduler( context *) noexcept; + scheduler() noexcept; scheduler( scheduler const&) = delete; scheduler & operator=( scheduler const&) = delete; virtual ~scheduler() noexcept; - void spawn( context *); + void main_context( context *) noexcept; - void run( context *); + void dispatching_context( intrusive_ptr< context >) noexcept; - bool wait_until( context *, - std::chrono::steady_clock::time_point const&); - - void yield( context *); - - void signal( context *); - - void remote_signal( context *); - - size_t ready_fibers() const noexcept; - - void set_sched_algo( std::unique_ptr< sched_algorithm >); + void dispatch() noexcept; }; }} diff --git a/include/boost/fiber/thread_local_ptr.hpp b/include/boost/fiber/thread_local_ptr.hpp deleted file mode 100644 index 7b387631..00000000 --- a/include/boost/fiber/thread_local_ptr.hpp +++ /dev/null @@ -1,14 +0,0 @@ - -// 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) -// - -#include - -# if defined(BOOST_WINDOWS) -#include -# else -#include -# endif diff --git a/include/boost/fiber/timed_mutex.hpp b/include/boost/fiber/timed_mutex.hpp deleted file mode 100644 index 67752814..00000000 --- a/include/boost/fiber/timed_mutex.hpp +++ /dev/null @@ -1,78 +0,0 @@ - -// 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_TIMED_MUTEX_H -#define BOOST_FIBERS_TIMED_MUTEX_H - -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -class BOOST_FIBERS_DECL timed_mutex { -private: - enum class mutex_status { - locked = 0, - unlocked - }; - - typedef detail::wait_queue< context > wait_queue_t; - - detail::spinlock splk_; - mutex_status state_; - context::id owner_; - wait_queue_t wait_queue_; - - bool lock_if_unlocked_(); - - bool try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time); - -public: - timed_mutex(); - - ~timed_mutex(); - - timed_mutex( timed_mutex const&) = delete; - timed_mutex & operator=( timed_mutex const&) = delete; - - void lock(); - - bool try_lock(); - - template< typename Clock, typename Duration > - bool try_lock_until( std::chrono::time_point< Clock, Duration > const& timeout_time_) { - std::chrono::steady_clock::time_point timeout_time( - detail::clock_cast( timeout_time_) ); - return try_lock_until_( timeout_time); - } - - template< typename Rep, typename Period > - bool try_lock_for( std::chrono::duration< Rep, Period > const& timeout_duration) { - return try_lock_until_( std::chrono::steady_clock::now() + timeout_duration); - } - - void unlock(); -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_TIMED_MUTEX_H diff --git a/include/boost/fiber/unbounded_channel.hpp b/include/boost/fiber/unbounded_channel.hpp deleted file mode 100644 index 07219c19..00000000 --- a/include/boost/fiber/unbounded_channel.hpp +++ /dev/null @@ -1,269 +0,0 @@ - -// 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_UNBOUNDED_CHANNEL_H -#define BOOST_FIBERS_UNBOUNDED_CHANNEL_H - -#include // std::move() -#include -#include -#include // std::allocator -#include // std::unique_lock -#include // std::forward() - -#include -#include - -#include -#include -#include -#include -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -template< typename T, typename Allocator = std::allocator< T > > -class unbounded_channel { -public: - typedef T value_type; - -private: - struct node { - typedef intrusive_ptr< node > ptr; - typedef typename std::allocator_traits< Allocator >::template rebind_alloc< node > allocator_type; - - std::size_t use_count; - allocator_type & alloc; - T va; - ptr nxt; - - explicit node( T const& t, allocator_type & alloc_) : - use_count( 0), - alloc( alloc_), - va( t), - nxt() { - } - - explicit node( T && t, allocator_type & alloc_) : - use_count( 0), - alloc( alloc_), - va( std::forward< T >( t) ), - nxt() { - } - - friend - void intrusive_ptr_add_ref( node * p) { - ++p->use_count; - } - - friend - void intrusive_ptr_release( node * p) { - if ( 0 == --p->use_count) { - allocator_type & alloc( p->alloc); - std::allocator_traits< allocator_type >::destroy( alloc, p); - std::allocator_traits< allocator_type >::deallocate( alloc, p, 1); - } - } - }; - - typedef typename std::allocator_traits< Allocator >::template rebind_alloc< node > allocator_type; - - enum class queue_status { - open = 0, - closed - }; - - allocator_type alloc_; - queue_status state_; - typename node::ptr head_; - typename node::ptr * tail_; - mutable mutex mtx_; - condition not_empty_cond_; - - bool is_closed_() const noexcept { - return queue_status::closed == state_; - } - - void close_( std::unique_lock< mutex > & lk) { - state_ = queue_status::closed; - lk.unlock(); - not_empty_cond_.notify_all(); - } - - bool is_empty_() const noexcept { - return ! head_; - } - - channel_op_status push_( typename node::ptr const& new_node, - std::unique_lock< mutex > & lk) { - if ( is_closed_() ) { - return channel_op_status::closed; - } - - return push_and_notify_( new_node, lk); - } - - channel_op_status push_and_notify_( typename node::ptr const& new_node, - std::unique_lock< mutex > & lk) { - try { - push_tail_( new_node); - lk.unlock(); - not_empty_cond_.notify_one(); - - return channel_op_status::success; - } catch (...) { - close_( lk); - throw; - } - } - - void push_tail_( typename node::ptr new_node) { - * tail_ = new_node; - tail_ = & new_node->nxt; - } - - value_type value_pop_( std::unique_lock< mutex > & lk) { - BOOST_ASSERT( ! is_empty_() ); - - try { - typename node::ptr old_head = pop_head_(); - return std::move( old_head->va); - } catch (...) { - close_( lk); - throw; - } - } - - typename node::ptr pop_head_() { - typename node::ptr old_head = head_; - head_ = old_head->nxt; - if ( ! head_) { - tail_ = & head_; - } - old_head->nxt.reset(); - return old_head; - } - -public: - unbounded_channel( Allocator const& alloc = Allocator() ) : - alloc_( alloc), - state_( queue_status::open), - head_(), - tail_( & head_), - mtx_(), - not_empty_cond_() { - } - - unbounded_channel( unbounded_channel const&) = delete; - unbounded_channel & operator=( unbounded_channel const&) = delete; - - void close() { - std::unique_lock< mutex > lk( mtx_); - close_( lk); - } - - channel_op_status push( value_type const& va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( va, alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_( new_node, lk); - } - - channel_op_status push( value_type && va) { - typename node::ptr new_node( - new ( alloc_.allocate( 1) ) node( std::forward< value_type >( va), alloc_) ); - std::unique_lock< mutex > lk( mtx_); - return push_( new_node, lk); - } - - channel_op_status pop( value_type & va) { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - not_empty_cond_.wait( lk); - } - - if ( is_closed_() && is_empty_() ) { - return channel_op_status::closed; - } - - va = value_pop_( lk); - return channel_op_status::success; - } - - value_type value_pop() { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - not_empty_cond_.wait( lk); - } - - if ( is_closed_() && is_empty_() ) { - throw logic_error("boost fiber: queue is closed"); - } - - return value_pop_( lk); - } - - channel_op_status try_pop( value_type & va) { - std::unique_lock< mutex > lk( mtx_); - - if ( is_closed_() && is_empty_() ) { - // let other fibers run - lk.unlock(); - this_fiber::yield(); - return channel_op_status::closed; - } - - if ( is_empty_() ) { - // let other fibers run - lk.unlock(); - this_fiber::yield(); - return channel_op_status::empty; - } - - va = value_pop_( lk); - return channel_op_status::success; - } - - template< typename Rep, typename Period > - channel_op_status pop_wait_for( value_type & va, - std::chrono::duration< Rep, Period > const& timeout_duration) { - return pop_wait_until( va, std::chrono::steady_clock::now() + timeout_duration); - } - - template< typename Clock, typename Duration > - channel_op_status pop_wait_until( value_type & va, - std::chrono::time_point< Clock, Duration > const& timeout_time) { - std::unique_lock< mutex > lk( mtx_); - - while ( ! is_closed_() && is_empty_() ) { - if ( cv_status::timeout == not_empty_cond_.wait_until( lk, timeout_time) ) - return channel_op_status::timeout; - } - - if ( is_closed_() && is_empty_() ) { - return channel_op_status::closed; - } - - va = value_pop_( lk); - return channel_op_status::success; - } -}; - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_UNBOUNDED_CHANNEL_H diff --git a/include/boost/fiber/windows/thread_local_ptr.hpp b/include/boost/fiber/windows/thread_local_ptr.hpp deleted file mode 100644 index 7b19a9b4..00000000 --- a/include/boost/fiber/windows/thread_local_ptr.hpp +++ /dev/null @@ -1,42 +0,0 @@ - -// 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_THREAD_LOCAL_PTR_H -#define BOOST_FIBERS_THREAD_LOCAL_PTR_H - -#include -#include -#include - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -# if defined(BOOST_MSVC) -# pragma warning(push) -//# pragma warning(disable:4251 4275) -# endif - -namespace boost { -namespace fibers { - -template< typename T > -struct thread_local_ptr : public boost::thread_specific_ptr< T > -{}; - -}} - -# if defined(BOOST_MSVC) -# pragma warning(pop) -# endif - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif - -#endif // BOOST_FIBERS_THREAD_LOCAL_PTR_H diff --git a/src/algorithm.cpp b/src/algorithm.cpp deleted file mode 100644 index ea157ded..00000000 --- a/src/algorithm.cpp +++ /dev/null @@ -1,34 +0,0 @@ - -// Copyright Oliver Kowalke / Nat Goodspeed 2015. -// 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) - -#include "boost/fiber/algorithm.hpp" - -#include "boost/fiber/context.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -//static -fiber_properties * -sched_algorithm_with_properties_base::get_properties( context * f) noexcept { - return f->get_properties(); -} - -//static -void -sched_algorithm_with_properties_base::set_properties( context * f, fiber_properties * props) noexcept { - f->set_properties( props); -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/barrier.cpp b/src/barrier.cpp deleted file mode 100644 index 89707912..00000000 --- a/src/barrier.cpp +++ /dev/null @@ -1,54 +0,0 @@ - -// 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) - -#include "boost/fiber/barrier.hpp" - -#include - -#include "boost/fiber/exceptions.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -barrier::barrier( std::size_t initial) : - initial_( initial), - current_( initial_), - cycle_( true), - mtx_(), - cond_() { - if ( 0 == initial) { - throw invalid_argument( static_cast< int >( std::errc::invalid_argument), - "boost fiber: zero initial barrier count"); - } -} - -bool -barrier::wait() { - std::unique_lock< mutex > lk( mtx_); - bool cycle( cycle_); - if ( 0 == --current_) { - cycle_ = ! cycle_; - current_ = initial_; - lk.unlock(); // no pessimization - cond_.notify_all(); - return true; - } else { - while ( cycle == cycle_) { - cond_.wait( lk); - } - } - return false; -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/condition.cpp b/src/condition.cpp deleted file mode 100644 index cf84ceb6..00000000 --- a/src/condition.cpp +++ /dev/null @@ -1,64 +0,0 @@ - -// 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) - -#include "boost/fiber/condition.hpp" - -#include "boost/fiber/context.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -condition::condition() : - splk_(), - wait_queue_() { -} - -condition::~condition() { - BOOST_ASSERT( wait_queue_.empty() ); -} - -void -condition::notify_one() { - context * f( nullptr); - - detail::spinlock_lock lk( splk_); - // get one waiting fiber - if ( ! wait_queue_.empty() ) { - f = & wait_queue_.front(); - wait_queue_.pop_front(); - } - lk.unlock(); - - // notify waiting fiber - if ( nullptr != f) { - context::active()->do_signal( f); - } -} - -void -condition::notify_all() { - wait_queue_t tmp; - - detail::spinlock_lock lk( splk_); - // get all waiting fibers - tmp.swap( wait_queue_); - lk.unlock(); - - // notify all waiting fibers - for ( context & f : tmp) { - context::active()->do_signal( & f); - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/context.cpp b/src/context.cpp index b954209d..5c5ad989 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -6,10 +6,7 @@ #include "boost/fiber/context.hpp" -#include "boost/fiber/algorithm.hpp" -#include "boost/fiber/exceptions.hpp" -#include "boost/fiber/fiber.hpp" -#include "boost/fiber/properties.hpp" +#include "boost/fiber/fixedsize_stack.hpp" #include "boost/fiber/scheduler.hpp" #ifdef BOOST_HAS_ABI_HEADERS @@ -20,10 +17,20 @@ namespace boost { namespace fibers { static context * main_context() { - static thread_local context mc; - static thread_local scheduler sched( & mc); - mc.set_scheduler( & sched); - return & mc; + // main fiber context for this thread + static thread_local context main_ctx; + // scheduler for this thread + static thread_local scheduler sched; + // attach scheduler to main fiber context + main_ctx.set_scheduler( & sched); + // attach main fiber context to scheduler + sched.main_context( & main_ctx); + // attach dispatching fiber context to scheduler + sched.dispatching_context( + make_context( + fixedsize_stack(), + & scheduler::dispatch, & sched) ); + return & main_ctx; } thread_local context * @@ -41,182 +48,59 @@ context::active( context * active) noexcept { } context::~context() { + BOOST_ASSERT( ! wait_is_linked() ); BOOST_ASSERT( wait_queue_.empty() ); - delete properties_; + BOOST_ASSERT( ! ready_is_linked() ); } void -context::release() { +context::set_scheduler( scheduler * s) { + BOOST_ASSERT( nullptr != s); + scheduler_ = s; +} + +scheduler * +context::get_scheduler() const noexcept { + return scheduler_; +} + +context::id +context::get_id() const noexcept { + return id( const_cast< context * >( this) ); +} + +void +context::resume() { + BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm + ctx_(); +} + +void +context::release() noexcept { BOOST_ASSERT( is_terminated() ); - wait_queue_t tmp; - - // get all waiting fibers - splk_.lock(); - tmp.swap( wait_queue_); - splk_.unlock(); - // notify all waiting fibers - for ( context * f : tmp) { - do_signal( f); + wait_queue_t::iterator e = wait_queue_.end(); + for ( wait_queue_t::iterator i = wait_queue_.begin(); i != e;) { + context * f = & ( * i); + i = wait_queue_.erase( i); + //FIXME: signal that f might resume } - - // release fiber-specific-data - for ( fss_data_t::value_type & data : fss_data_) { - data.second.do_cleanup(); - } - fss_data_.clear(); } bool -context::join( context * f) { - BOOST_ASSERT( nullptr != f); - - detail::spinlock_lock lk( splk_); - if ( is_terminated() ) { - return false; - } - f->set_waiting(); - wait_queue_.push_back( f); - return true; +context::wait_is_linked() { + return wait_hook_.is_linked(); } void -context::interruption_blocked( bool blck) noexcept { - if ( blck) { - flags_ |= flag_interruption_blocked; - } else { - flags_ &= ~flag_interruption_blocked; - } -} - -void -context::request_interruption( bool req) noexcept { - if ( req) { - flags_ |= flag_interruption_requested; - } else { - flags_ &= ~flag_interruption_requested; - } -} - -void * -context::get_fss_data( void const * vp) const { - uintptr_t key( reinterpret_cast< uintptr_t >( vp) ); - fss_data_t::const_iterator i( fss_data_.find( key) ); - - return fss_data_.end() != i ? i->second.vp : nullptr; -} - -void -context::set_fss_data( void const * vp, - detail::fss_cleanup_function::ptr_t const& cleanup_fn, - void * data, - bool cleanup_existing) { - BOOST_ASSERT( cleanup_fn); - - uintptr_t key( reinterpret_cast< uintptr_t >( vp) ); - fss_data_t::iterator i( fss_data_.find( key) ); - - if ( fss_data_.end() != i) { - if( cleanup_existing) { - i->second.do_cleanup(); - } - if ( nullptr != data) { - fss_data_.insert( - i, - std::make_pair( - key, - fss_data( data, cleanup_fn) ) ); - } else { - fss_data_.erase( i); - } - } else { - fss_data_.insert( - std::make_pair( - key, - fss_data( data, cleanup_fn) ) ); - } -} - -void -context::set_properties( fiber_properties * props) { - delete properties_; - properties_ = props; -} - -void -context::do_spawn( fiber const& f) { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - scheduler_->spawn( f.impl_.get() ); -} - -void -context::do_schedule() { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - scheduler_->run( this); +context::wait_unlink() { + wait_hook_.unlink(); } bool -context::do_wait_until( std::chrono::steady_clock::time_point const& time_point) { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - return scheduler_->wait_until( this, time_point); -} - -void -context::do_yield() { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - scheduler_->yield( this); -} - -void -context::do_join( context * f) { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - BOOST_ASSERT( nullptr != f); - BOOST_ASSERT( f != active_); - - if ( f->join( this) ) { - scheduler_->run( this); - } -} - -void -context::do_signal( context * f) { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - BOOST_ASSERT( nullptr != f); - - if ( scheduler_ == f->scheduler_) { - // local scheduler - scheduler_->signal( f); - } else { - // scheduler in another thread - f->scheduler_->remote_signal( f); - } -} - -std::size_t -context::do_ready_fibers() const noexcept { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - return scheduler_->ready_fibers(); -} - -void -context::do_set_sched_algo( std::unique_ptr< sched_algorithm > algo) { - BOOST_ASSERT( nullptr != scheduler_); - BOOST_ASSERT( this == active_); - - scheduler_->set_sched_algo( std::move( algo) ); +context::ready_is_linked() { + return ready_hook_.is_linked(); } }} diff --git a/src/fiber.cpp b/src/fiber.cpp index be45f8a3..d914c3a4 100644 --- a/src/fiber.cpp +++ b/src/fiber.cpp @@ -10,10 +10,6 @@ #include -#include "boost/fiber/context.hpp" -#include "boost/fiber/exceptions.hpp" -#include "boost/fiber/operations.hpp" - #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX #endif @@ -24,56 +20,7 @@ namespace fibers { void fiber::start_() { impl_->set_ready(); - context::active()->do_spawn( * this); -} - -void -fiber::join() { - BOOST_ASSERT( impl_); - - if ( boost::this_fiber::get_id() == get_id() ) { - throw fiber_resource_error( static_cast< int >( std::errc::resource_deadlock_would_occur), - "boost fiber: trying to join itself"); - } - - if ( ! joinable() ) { - throw fiber_resource_error( static_cast< int >( std::errc::invalid_argument), - "boost fiber: fiber not joinable"); - } - - context::active()->do_join( impl_.get() ); - - // check if joined fiber was interrupted - std::exception_ptr except( impl_->get_exception() ); - - ptr_t tmp; - tmp.swap( impl_); - - // re-throw excpetion - if ( except) { - std::rethrow_exception( except); - } -} - -void -fiber::detach() { - BOOST_ASSERT( impl_); - - if ( ! joinable() ) { - throw fiber_resource_error( static_cast< int >( std::errc::invalid_argument), - "boost fiber: fiber not joinable"); - } - - ptr_t tmp; - tmp.swap( impl_); -} - -void -fiber::interrupt() noexcept { - BOOST_ASSERT( impl_); - - impl_->request_interruption( true); - context::active()->do_signal( impl_.get() ); + //FIXME: spawn new fiber-context } }} diff --git a/src/future.cpp b/src/future.cpp deleted file mode 100644 index 1fe1afb8..00000000 --- a/src/future.cpp +++ /dev/null @@ -1,72 +0,0 @@ - -// 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) - -#include "boost/fiber/exceptions.hpp" - -namespace boost { -namespace fibers { - -class future_error_category : public std::error_category { -public: - virtual const char* name() const noexcept { - return "future"; - } - - virtual std::error_condition default_error_condition( int ev) const noexcept { - switch ( ev) { - case 1: return std::error_condition( - static_cast< int >( future_errc::broken_promise), - future_category() ); - case 2: return std::error_condition( - static_cast< int >( future_errc::future_already_retrieved), - future_category() ); - case 3: return std::error_condition( - static_cast< int >( future_errc::promise_already_satisfied), - future_category() ); - case 4: return std::error_condition( - static_cast< - int >( future_errc::no_state), - future_category() ); - default: - return std::error_condition( - static_cast< - int >( future_errc::unknown), - future_category() ); - } - } - - virtual bool equivalent( std::error_code const& code, int condition) const noexcept { - return * this == code.category() && - static_cast< int >( default_error_condition( code.value() ).value() ) == condition; - } - - virtual std::string message( int ev) const { - switch ( static_cast< future_errc >( ev) ) { - case future_errc::unknown: - return std::string("Unknown error"); - case future_errc::broken_promise: - return std::string("The associated promise has been destructed prior " - "to the associated state becoming ready."); - case future_errc::future_already_retrieved: - return std::string("The future has already been retrieved from " - "the promise or packaged_task."); - case future_errc::promise_already_satisfied: - return std::string("The state of the promise has already been set."); - case future_errc::no_state: - return std::string("Operation not permitted on an object without " - "an associated state."); - } - return std::string("unspecified future_errc value\n"); - } -}; - -BOOST_FIBERS_DECL -std::error_category const& future_category() noexcept { - static fibers::future_error_category cat; - return cat; -} - -}} diff --git a/src/interruption.cpp b/src/interruption.cpp deleted file mode 100644 index 20908b4f..00000000 --- a/src/interruption.cpp +++ /dev/null @@ -1,70 +0,0 @@ - -// 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) -// -// based on boost.thread - -#include "boost/fiber/interruption.hpp" - -#include "boost/fiber/context.hpp" -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/exceptions.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace this_fiber { - -disable_interruption::disable_interruption() noexcept : - set_( ( fibers::context::active()->interruption_blocked() ) ) { - if ( ! set_) { - fibers::context::active()->interruption_blocked( true); - } -} - -disable_interruption::~disable_interruption() noexcept { - if ( ! set_) { - fibers::context::active()->interruption_blocked( false); - } -} - -restore_interruption::restore_interruption( disable_interruption & disabler) noexcept : - disabler_( disabler) { - if ( ! disabler_.set_) { - fibers::context::active()->interruption_blocked( false); - } -} - -restore_interruption::~restore_interruption() noexcept { - if ( ! disabler_.set_) { - fibers::context::active()->interruption_blocked( true); - } -} - -BOOST_FIBERS_DECL -bool interruption_enabled() noexcept { - return ! fibers::context::active()->interruption_blocked(); -} - -BOOST_FIBERS_DECL -bool interruption_requested() noexcept { - return fibers::context::active()->interruption_requested(); -} - -BOOST_FIBERS_DECL -void interruption_point() { - if ( interruption_requested() && interruption_enabled() ) { - fibers::context::active()->request_interruption( false); - throw fibers::fiber_interrupted(); - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/mutex.cpp b/src/mutex.cpp deleted file mode 100644 index 400adc60..00000000 --- a/src/mutex.cpp +++ /dev/null @@ -1,117 +0,0 @@ - -// 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) - -#include "boost/fiber/mutex.hpp" - -#include - -#include - -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/interruption.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -bool -mutex::lock_if_unlocked_() { - if ( mutex_status::unlocked != state_) { - return false; - } - - state_ = mutex_status::locked; - BOOST_ASSERT( ! owner_); - owner_ = context::active()->get_id(); - return true; -} - -mutex::mutex() : - splk_(), - state_( mutex_status::unlocked), - owner_(), - wait_queue_() { -} - -mutex::~mutex() { - BOOST_ASSERT( ! owner_); - BOOST_ASSERT( wait_queue_.empty() ); -} - -void -mutex::lock() { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - f->do_schedule(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -bool -mutex::try_lock() { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return true; - } - - lk.unlock(); - - // let other fiber release the lock - context::active()->do_yield(); - return false; -} - -void -mutex::unlock() { - BOOST_ASSERT( mutex_status::locked == state_); - BOOST_ASSERT( context::active()->get_id() == owner_); - - detail::spinlock_lock lk( splk_); - context * f( nullptr); - if ( ! wait_queue_.empty() ) { - f = & wait_queue_.front(); - wait_queue_.pop_front(); - BOOST_ASSERT( nullptr != f); - } - owner_ = context::id(); - state_ = mutex_status::unlocked; - lk.unlock(); - - if ( nullptr != f) { - context::active()->do_signal( f); - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/properties.cpp b/src/properties.cpp deleted file mode 100644 index 30e500b2..00000000 --- a/src/properties.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// 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) - -#include "boost/fiber/properties.hpp" - -#include - -#include "boost/fiber/algorithm.hpp" -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/context.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -void fiber_properties::notify() { - BOOST_ASSERT( sched_algo_); - // Application code might change an important property for any fiber at - // any time. The fiber in question might be ready, running or waiting. - // Significantly, only a fiber which is ready but not actually running is - // in the sched_algorithm's ready queue. Don't bother the sched_algorithm - // with a change to a fiber it's not currently tracking: it will do the - // right thing next time the fiber is passed to its awakened() method. - if ( fiber_->is_ready() ) { - static_cast< sched_algorithm_with_properties_base * >( sched_algo_)-> - property_change_( fiber_, this); - } -} - -}} // boost::fibers - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/recursive_mutex.cpp b/src/recursive_mutex.cpp deleted file mode 100644 index a5541f36..00000000 --- a/src/recursive_mutex.cpp +++ /dev/null @@ -1,125 +0,0 @@ - -// 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) - -#include "boost/fiber/recursive_mutex.hpp" - -#include - -#include - -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/interruption.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -bool -recursive_mutex::lock_if_unlocked_() { - if ( mutex_status::unlocked == state_) { - state_ = mutex_status::locked; - BOOST_ASSERT( ! owner_); - owner_ = context::active()->get_id(); - ++count_; - return true; - } else if ( context::active()->get_id() == owner_) { - ++count_; - return true; - } - - return false; -} - -recursive_mutex::recursive_mutex() : - splk_(), - state_( mutex_status::unlocked), - owner_(), - count_( 0), - wait_queue_() { -} - -recursive_mutex::~recursive_mutex() { - BOOST_ASSERT( ! owner_); - BOOST_ASSERT( 0 == count_); - BOOST_ASSERT( wait_queue_.empty() ); -} - -void -recursive_mutex::lock() { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - f->do_schedule(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -bool -recursive_mutex::try_lock() { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return true; - } - - lk.unlock(); - - // let other fiber release the lock - context::active()->do_yield(); - return false; -} - -void -recursive_mutex::unlock() { - BOOST_ASSERT( mutex_status::locked == state_); - BOOST_ASSERT( context::active()->get_id() == owner_); - - detail::spinlock_lock lk( splk_); - context * f( nullptr); - if ( 0 == --count_) { - if ( ! wait_queue_.empty() ) { - f = & wait_queue_.front(); - wait_queue_.pop_front(); - BOOST_ASSERT( nullptr != f); - } - owner_ = context::id(); - state_ = mutex_status::unlocked; - lk.unlock(); - - if ( nullptr != f) { - context::active()->do_signal( f); - } - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/recursive_timed_mutex.cpp b/src/recursive_timed_mutex.cpp deleted file mode 100644 index b4a639b2..00000000 --- a/src/recursive_timed_mutex.cpp +++ /dev/null @@ -1,164 +0,0 @@ - -// 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) - -#include "boost/fiber/recursive_timed_mutex.hpp" - -#include - -#include - -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/interruption.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -bool -recursive_timed_mutex::lock_if_unlocked_() { - if ( mutex_status::unlocked == state_) { - state_ = mutex_status::locked; - BOOST_ASSERT( ! owner_); - owner_ = context::active()->get_id(); - ++count_; - return true; - } else if ( context::active()->get_id() == owner_) { - ++count_; - return true; - } - - return false; -} - -recursive_timed_mutex::recursive_timed_mutex() : - splk_(), - state_( mutex_status::unlocked), - owner_(), - count_( 0), - wait_queue_() { -} - -recursive_timed_mutex::~recursive_timed_mutex() { - BOOST_ASSERT( ! owner_); - BOOST_ASSERT( 0 == count_); - BOOST_ASSERT( wait_queue_.empty() ); -} - -void -recursive_timed_mutex::lock() { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - f->do_schedule(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -bool -recursive_timed_mutex::try_lock() { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return true; - } - - lk.unlock(); - - // let other fiber release the lock - context::active()->do_yield(); - return false; -} - -bool -recursive_timed_mutex::try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( std::chrono::steady_clock::now() > timeout_time) { - return false; - } - - if ( lock_if_unlocked_() ) { - return true; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber until notified or timed-out - if ( ! f->do_wait_until( timeout_time) ) { - lk.lock(); - f->wait_unlink(); - lk.unlock(); - return false; - } - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -void -recursive_timed_mutex::unlock() { - BOOST_ASSERT( mutex_status::locked == state_); - BOOST_ASSERT( context::active()->get_id() == owner_); - - detail::spinlock_lock lk( splk_); - context * f( nullptr); - if ( 0 == --count_) { - if ( ! wait_queue_.empty() ) { - f = & wait_queue_.front(); - wait_queue_.pop_front(); - BOOST_ASSERT( nullptr != f); - } - owner_ = context::id(); - state_ = mutex_status::unlocked; - lk.unlock(); - - if ( nullptr != f) { - context::active()->do_signal( f); - } - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/round_robin.cpp b/src/round_robin.cpp deleted file mode 100644 index aff5bfdc..00000000 --- a/src/round_robin.cpp +++ /dev/null @@ -1,47 +0,0 @@ - -// 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) - -#include "boost/fiber/round_robin.hpp" - -#include - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -void -round_robin::awakened( context * f) { - BOOST_ASSERT( nullptr != f); - - BOOST_ASSERT( ! f->runnable_is_linked() ); - runnable_queue_.push_back( * f); -} - -context * -round_robin::pick_next() { - context * victim( nullptr); - if ( ! runnable_queue_.empty() ) { - victim = & runnable_queue_.front(); - runnable_queue_.pop_front(); - BOOST_ASSERT( nullptr != victim); - BOOST_ASSERT( ! victim->runnable_is_linked() ); - } - return victim; -} - -std::size_t -round_robin::ready_fibers() const noexcept { - return runnable_queue_.size(); -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif diff --git a/src/scheduler.cpp b/src/scheduler.cpp index e9587910..57a3cda1 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -6,16 +6,9 @@ #include "boost/fiber/scheduler.hpp" -#include -#include // std::this_thread::sleep_until() -#include - #include -#include "boost/fiber/algorithm.hpp" -#include "boost/fiber/exceptions.hpp" -#include "boost/fiber/interruption.hpp" -#include "boost/fiber/round_robin.hpp" +#include "boost/fiber/context.hpp" #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -24,107 +17,6 @@ namespace boost { namespace fibers { -scheduler::scheduler( context * main_context) noexcept : - ev_(), - sched_algo_( new round_robin() ), - main_context_( main_context), - ready_queue_(), - sleep_queue_(), - terminated_queue_(), - remote_ready_queue_() { -} - -scheduler::~scheduler() noexcept { - BOOST_ASSERT( context::active() == main_context_); - for (;;) { - { - // move all fibers in remote-ready-queue to runnable-queue - remote_ready_queue_.consume_all([=](context * f){ - if ( ! f->ready_is_linked() && - ! f->runnable_is_linked() ) { - f->set_ready(); - ready_queue_.push_back( * f); - }}); - // move all fibers in ready-queue to running-queue - ready_queue_t::iterator e = ready_queue_.end(); - for ( ready_queue_t::iterator i = ready_queue_.begin(); i != e;) { - context * f = & ( * i); - BOOST_ASSERT( f->is_ready() ); - - i = ready_queue_.erase( i); - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - // timed_mutex::try_lock_until() -> add f to waiting-queue - // -> add f to sleeping-queue - if ( f->sleep_is_linked() ) { - f->sleep_unlink(); - } - sched_algo_->awakened( f); - } - } - { - // interrupt all fibers in the sleep-queue - sleep_queue_t::iterator e = sleep_queue_.end(); - for ( sleep_queue_t::iterator i = sleep_queue_.begin(); i != e;) { - context * f = & ( * i); - BOOST_ASSERT( ! f->is_running() ); - BOOST_ASSERT( ! f->is_terminated() ); - // request interruption - f->request_interruption( true); - // set to state_ready - f->set_ready(); - // unlink after accesing iterator - f->time_point_reset(); - i = sleep_queue_.erase( i); - // Pass the newly-unlinked context* to sched_algo. - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - sched_algo_->awakened( f); - } - } - // pop new fiber from runnable-queue - context * f( sched_algo_->pick_next() ); - if ( nullptr != f) { - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in ready-queue"); - // set scheduler - f->set_scheduler( this); - // add active-fiber to joinig-list of f - // fiber::join() should not fail because fiber f is in state_ready - // so main-fiber should be in the waiting-queue of fiber f - f->join( main_context_); - // set main-fiber to state_waiting - main_context_->set_waiting(); - // push main-fiber to waiting-queue - BOOST_ASSERT( ! main_context_->runnable_is_linked() ); - ready_queue_.push_back( * main_context_); - // resume fiber f - resume_( main_context_, f); - } else if ( sleep_queue_.empty() ) { - // ready- and waiting-queue are empty so we can quit - break; - } - } - // destroy terminated fibers from terminated-queue - for ( context * f : terminated_queue_) { - BOOST_ASSERT( f->is_terminated() ); - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - BOOST_ASSERT( ! f->wait_is_linked() ); - intrusive_ptr_release( f); // might call ~context() - } - terminated_queue_.clear(); - BOOST_ASSERT( context::active() == main_context_); - BOOST_ASSERT( ready_queue_.empty() ); - BOOST_ASSERT( sleep_queue_.empty() ); - BOOST_ASSERT( terminated_queue_.empty() ); - BOOST_ASSERT( 0 == sched_algo_->ready_fibers() ); -} - void scheduler::resume_( context * af, context * f) { BOOST_ASSERT( nullptr != af); @@ -146,200 +38,54 @@ scheduler::resume_( context * af, context * f) { f->set_scheduler( af->get_scheduler() ); // assign new fiber to active-fiber context::active( f); - // push terminated fibers to terminated-queue - if ( af->is_terminated() ) { - BOOST_ASSERT( ! af->runnable_is_linked() ); - terminated_queue_.push_back( af); - } // resume active-fiber == f f->resume(); } -void -scheduler::spawn( context * f) { - BOOST_ASSERT( nullptr != f); - BOOST_ASSERT( f->is_ready() ); - BOOST_ASSERT( f != context::active() ); - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - // add new fiber to the scheduler - f->set_scheduler( this); - sched_algo_->awakened( f); +scheduler::scheduler() noexcept : + main_ctx_( nullptr), + dispatching_ctx_( nullptr), + ready_queue_() { +} + +scheduler::~scheduler() noexcept { + BOOST_ASSERT( nullptr != main_ctx_); + BOOST_ASSERT( dispatching_ctx_); + BOOST_ASSERT( context::active() == main_ctx_); + + // FIXME: signal dispatching context termination + // wait till dispatching context agrees on termination + + // reset intrusive-pointer to dispatching context + // should destroy dispatching context stack + dispatching_ctx_.reset(); } void -scheduler::run( context * af) { - BOOST_ASSERT( nullptr != af); - BOOST_ASSERT( context::active() == af); - for (;;) { - { - // move all fibers in remote-ready-queue to runnable-queue - remote_ready_queue_.consume_all([=](context * f){ - f->set_ready(); - ready_queue_.push_back( * f); - }); - // move all fibers in ready-queue to runnable-queue - ready_queue_t::iterator e = ready_queue_.end(); - for ( ready_queue_t::iterator i = ready_queue_.begin(); i != e;) { - context * f = & ( * i); - BOOST_ASSERT( f->is_ready() ); +scheduler::main_context( context * main_ctx) noexcept { + BOOST_ASSERT( nullptr != main_ctx); + main_ctx_ = main_ctx; +} - i = ready_queue_.erase( i); - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - // timed_mutex::try_lock_until() -> add f to waiting-queue - // -> add f to sleeping-queue - if ( f->sleep_is_linked() ) { - f->sleep_unlink(); - } - sched_algo_->awakened( f); - } - } - { - // move sleeping fibers where the deadline has reached - // to runnable-queue - // sleep-queue is sorted (ascending) - std::chrono::steady_clock::time_point now( - std::chrono::steady_clock::now() ); - sleep_queue_t::iterator e( sleep_queue_.end() ); - for ( sleep_queue_t::iterator i( sleep_queue_.begin() ); i != e;) { - context * f = & ( * i); - BOOST_ASSERT( ! f->is_running() ); - BOOST_ASSERT( ! f->is_terminated() ); - // set fiber to state_ready if deadline was reached - if ( f->time_point() <= now) { - f->set_ready(); - } else { - break; // first element with f->time_point() > now; leave for-loop - } - if ( f->is_ready() ) { - i = sleep_queue_.erase( i); - // unlink only after accessing iterator - f->time_point_reset(); - // Pass the newly-unlinked context* to sched_algo. - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - sched_algo_->awakened( f); - } else { - ++i; - } - } - } - // pop new fiber from runnable-queue - context * f( sched_algo_->pick_next() ); - if ( nullptr != f) { - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - BOOST_ASSERT_MSG( f->is_ready(), "fiber with invalid state in runnable-queue"); - // resume fiber f - resume_( af, f); - // destroy terminated fibers from terminated-queue - for ( context * f : terminated_queue_) { - BOOST_ASSERT( f->is_terminated() ); - BOOST_ASSERT( ! f->runnable_is_linked() ); - BOOST_ASSERT( ! f->ready_is_linked() ); - BOOST_ASSERT( ! f->sleep_is_linked() ); - BOOST_ASSERT( ! f->wait_is_linked() ); - intrusive_ptr_release( f); // might call ~context() - } - terminated_queue_.clear(); - return; - } else { - // no fibers ready to run - // set deadline to highest value - std::chrono::steady_clock::time_point tp( - (std::chrono::steady_clock::time_point::max)()); - // get lowest deadline from sleep-queue - sleep_queue_t::iterator i( sleep_queue_.begin() ); - if ( sleep_queue_.end() != i) { - tp = i->time_point(); - } - // wait till signaled or timed-out - ev_.reset( tp); - } +void +scheduler::dispatching_context( intrusive_ptr< context > dispatching_ctx) noexcept { + BOOST_ASSERT( dispatching_ctx); + dispatching_ctx_.swap( dispatching_ctx); + // add dispatching context to ready-queue + // so it is the first element in the ready-queue + // if the main context tries to suspend the first time + // the dispatching context is resumed and + // scheduler::dispatch() is executed + ready_queue_.push_back( * dispatching_ctx_.get() ); +} + +void +scheduler::dispatch() noexcept { + if ( ready_queue.empty() ) { + // FIXME: sleep } } -bool -scheduler::wait_until( context * af, - std::chrono::steady_clock::time_point const& timeout_time) { - BOOST_ASSERT( nullptr != af); - BOOST_ASSERT( context::active() == af); - // from this_fiber::sleep() -> running - // from timed_mutex::lock_until() -> waiting - BOOST_ASSERT( af->is_running() || af->is_waiting() ); - // set to state_waiting - af->set_waiting(); - // push active-fiber to sleep-queue - af->time_point( timeout_time); - BOOST_ASSERT( ! af->sleep_is_linked() ); - sleep_queue_.insert( * af); - // switch to another fiber - run( af); - // fiber has been resumed - // check if fiber was interrupted - this_fiber::interruption_point(); - // check if deadline has reached - return std::chrono::steady_clock::now() < timeout_time; -} - -void -scheduler::yield( context * af) { - BOOST_ASSERT( nullptr != af); - BOOST_ASSERT( context::active() == af); - BOOST_ASSERT( af->is_running() ); - // set active-fiber to state_ready - af->set_ready(); - // push active-fiber to ready-queue - BOOST_ASSERT( ! af->ready_is_linked() ); - ready_queue_.push_back( * af); - // schedule another fiber - run( af); - // fiber has been resumed - // NOTE: do not check if fiber was interrupted - // yield() should not be an interruption point -} - -void -scheduler::signal( context * f) { - BOOST_ASSERT( nullptr != f); - BOOST_ASSERT( ! f->is_terminated() ); - - // a fiber MUST NOT be inserted multiple times - // in runnable- or ready-queue - if ( ! f->ready_is_linked() && - ! f->runnable_is_linked() ) { - // set fiber to state_ready - f->set_ready(); - // put reafy fiber ot read-queue - ready_queue_.push_back( * f); - } -} - -void -scheduler::remote_signal( context * f) { - BOOST_ASSERT( nullptr != f); - BOOST_ASSERT( ! f->is_terminated() ); - - while ( ! remote_ready_queue_.bounded_push( f) ) { - context::active()->do_yield(); - } - ev_.set(); -} - -std::size_t -scheduler::ready_fibers() const noexcept { - return sched_algo_->ready_fibers(); -} - -void -scheduler::set_sched_algo( std::unique_ptr< sched_algorithm > algo) { - sched_algo_ = std::move( algo); -} - }} #ifdef BOOST_HAS_ABI_HEADERS diff --git a/src/timed_mutex.cpp b/src/timed_mutex.cpp deleted file mode 100644 index 40e88094..00000000 --- a/src/timed_mutex.cpp +++ /dev/null @@ -1,156 +0,0 @@ - -// 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) - -#include "boost/fiber/timed_mutex.hpp" - -#include - -#include - -#include "boost/fiber/scheduler.hpp" -#include "boost/fiber/interruption.hpp" - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_PREFIX -#endif - -namespace boost { -namespace fibers { - -bool -timed_mutex::lock_if_unlocked_() { - if ( mutex_status::unlocked != state_) { - return false; - } - - state_ = mutex_status::locked; - BOOST_ASSERT( ! owner_); - owner_ = context::active()->get_id(); - return true; -} - -timed_mutex::timed_mutex() : - splk_(), - state_( mutex_status::unlocked), - owner_(), - wait_queue_() { -} - -timed_mutex::~timed_mutex() { - BOOST_ASSERT( ! owner_); - BOOST_ASSERT( wait_queue_.empty() ); -} - -void -timed_mutex::lock() { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber - f->do_schedule(); - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -bool -timed_mutex::try_lock() { - detail::spinlock_lock lk( splk_); - - if ( lock_if_unlocked_() ) { - return true; - } - - lk.unlock(); - - // let other fiber release the lock - context::active()->do_yield(); - return false; -} - -bool -timed_mutex::try_lock_until_( std::chrono::steady_clock::time_point const& timeout_time) { - context * f( context::active() ); - BOOST_ASSERT( nullptr != f); - for (;;) { - detail::spinlock_lock lk( splk_); - - if ( std::chrono::steady_clock::now() > timeout_time) { - return false; - } - - if ( lock_if_unlocked_() ) { - return true; - } - - try { - // store this fiber in order to be notified later - BOOST_ASSERT( ! f->wait_is_linked() ); - f->set_waiting(); - wait_queue_.push_back( * f); - lk.unlock(); - - // check if fiber was interrupted - this_fiber::interruption_point(); - // suspend this fiber until notified or timed-out - if ( ! context::active()->do_wait_until( timeout_time) ) { - lk.lock(); - f->wait_unlink(); - lk.unlock(); - return false; - } - } catch (...) { - detail::spinlock_lock lk( splk_); - f->wait_unlink(); - throw; - } - } -} - -void -timed_mutex::unlock() { - BOOST_ASSERT( mutex_status::locked == state_); - BOOST_ASSERT( context::active()->get_id() == owner_); - - detail::spinlock_lock lk( splk_); - context * f( nullptr); - if ( ! wait_queue_.empty() ) { - f = & wait_queue_.front(); - wait_queue_.pop_front(); - BOOST_ASSERT( nullptr != f); - } - owner_ = context::id(); - state_ = mutex_status::unlocked; - lk.unlock(); - - if ( nullptr != f) { - context::active()->do_signal( f); - } -} - -}} - -#ifdef BOOST_HAS_ABI_HEADERS -# include BOOST_ABI_SUFFIX -#endif