From 61c3fd4589eff4c1ea015bc6747e9423be7d4ce1 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Mon, 10 Jun 2013 20:11:52 +0200 Subject: [PATCH] some fixes --- examples/Jamfile.v2 | 2 + examples/segmented_stack.cpp | 64 +++++++++++++++++++ include/boost/fiber/fiber.hpp | 16 ++--- .../boost/fiber/future/detail/future_base.hpp | 8 +-- .../boost/fiber/future/detail/task_object.hpp | 8 +-- include/boost/fiber/future/future.hpp | 9 ++- include/boost/fiber/future/packaged_task.hpp | 45 ++++--------- include/boost/fiber/round_robin.hpp | 42 ++++++++++++ include/boost/fiber/stack_context.hpp | 2 +- src/detail/scheduler.cpp | 4 +- src/detail/segmented_stack_allocator.cpp | 8 +-- src/fiber.cpp | 6 +- src/future.cpp | 2 +- src/interruption.cpp | 8 +-- src/round_robin.cpp | 42 ++++-------- 15 files changed, 168 insertions(+), 98 deletions(-) create mode 100644 examples/segmented_stack.cpp diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 index 486909da..62de514f 100644 --- a/examples/Jamfile.v2 +++ b/examples/Jamfile.v2 @@ -12,6 +12,7 @@ project boost/fiber/example ../build//boost_fibers /boost/context//boost_context /boost/system//boost_system + /boost/thread//boost_thread static multi ; @@ -21,3 +22,4 @@ exe future : future.cpp ; exe join : join.cpp ; exe ping_pong : ping_pong.cpp ; exe simple : simple.cpp ; +exe segmented_stack : segmented_stack.cpp ; diff --git a/examples/segmented_stack.cpp b/examples/segmented_stack.cpp new file mode 100644 index 00000000..8c5e1239 --- /dev/null +++ b/examples/segmented_stack.cpp @@ -0,0 +1,64 @@ + +// Copyright Oliver Kowalke 2009. +// 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 + +int count = 20; +#if defined(BOOST_USE_SEGMENTED_STACKS) +void access( char *buf) __attribute__ ((noinline)); +#endif +void access( char *buf) +{ + buf[0] = '\0'; +} + +void bar( int i) +{ + char buf[4 * 1024]; + + if ( i > 0) + { + access( buf); + std::cout << i << ". iteration" << std::endl; + bar( i - 1); + } +} + +void foo() +{ + bar( count); + boost::this_fiber::yield(); +} + +void thread_fn() +{ + boost::fibers::round_robin ds; + boost::fibers::scheduling_algorithm( & ds); + + { + boost::fibers::fiber f( foo); + f.join(); + } +} + +int main( int argc, char * argv[]) +{ + std::cout << "using standard stacks: allocates " << count << " * 4kB on stack, "; + std::cout << "initial stack size = " << boost::fibers::stack_allocator::default_stacksize() / 1024 << "kB" << std::endl; +#if defined(BOOST_USE_SEGMENTED_STACKS) + std::cout << "application should not fail" << std::endl; +#else + std::cout << "application might fail" << std::endl; +#endif + + boost::thread( thread_fn).join(); + + return 0; +} diff --git a/include/boost/fiber/fiber.hpp b/include/boost/fiber/fiber.hpp index 7d276f5c..72eda328 100644 --- a/include/boost/fiber/fiber.hpp +++ b/include/boost/fiber/fiber.hpp @@ -181,7 +181,7 @@ public: template< typename Fn, typename StackAllocator, typename Allocator > explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr, StackAllocator const& stack_alloc, - Allocator< fiber > const& alloc, + Allocator const& alloc, typename disable_if< is_same< typename decay< Fn >::type, fiber >, dummy * @@ -215,7 +215,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } @@ -236,7 +236,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } @@ -256,7 +256,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } @@ -277,7 +277,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } @@ -298,7 +298,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } @@ -318,7 +318,7 @@ public: typename object_t::allocator_t a( alloc); fiber_data_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) ); + ::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) ); start_fiber_(); } #endif @@ -348,7 +348,7 @@ public: { fiber_data_.swap( other.fiber_data_); } bool joinable() const BOOST_NOEXCEPT - { return fiber_data_ /* && ! fiber_data_->is_terminated() */; } + { return 0 != fiber_data_.get() /* && ! fiber_data_->is_terminated() */; } id get_id() const BOOST_NOEXCEPT { return fiber_data_ ? fiber_data_->get_id() : id(); } diff --git a/include/boost/fiber/future/detail/future_base.hpp b/include/boost/fiber/future/detail/future_base.hpp index c651ade6..79176508 100644 --- a/include/boost/fiber/future/detail/future_base.hpp +++ b/include/boost/fiber/future/detail/future_base.hpp @@ -53,7 +53,7 @@ private: //TODO: set broken_exception if future was not already done // notify all waiters if ( ! ready_) - set_exception_( copy_exception( broken_promise() ) ); + set_exception_( boost::copy_exception( broken_promise() ) ); } void set_value_( R const& value) @@ -164,7 +164,7 @@ public: // an exception is thrown if there is no shared state or the shared state already // stores a value or exception unique_lock< mutex > lk( mtx_); - set_value_( boot::move( value) ); + set_value_( boost::move( value) ); } #else void set_value( BOOST_RV_REF( R) value) @@ -245,7 +245,7 @@ private: //TODO: set broken_exception if future was not already done // notify all waiters if ( ! ready_) - set_exception_( copy_exception( broken_promise() ) ); + set_exception_( boost::copy_exception( broken_promise() ) ); } void set_value_( R & value) @@ -388,7 +388,7 @@ private: //TODO: set broken_exception if future was not already done // notify all waiters if ( ! ready_) - set_exception_( copy_exception( broken_promise() ) ); + set_exception_( boost::copy_exception( broken_promise() ) ); } void set_value_() diff --git a/include/boost/fiber/future/detail/task_object.hpp b/include/boost/fiber/future/detail/task_object.hpp index 70e4ac9a..f4c92bff 100644 --- a/include/boost/fiber/future/detail/task_object.hpp +++ b/include/boost/fiber/future/detail/task_object.hpp @@ -32,7 +32,7 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES task_object( Fn && fn, allocator_t const& alloc) : task_base< R >(), - fn_( boost::forward( fn) ), alloc_( alloc) + fn_( forward< Fn >( fn) ), alloc_( alloc) {} #else task_object( Fn const& fn, allocator_t const& alloc) : @@ -42,7 +42,7 @@ public: task_object( BOOST_RV_REF( Fn) fn, allocator_t const& alloc) : task_base< R >(), - fn_( boost::forward( fn) ), alloc_( alloc) + fn_( fn), alloc_( alloc) {} #endif @@ -85,7 +85,7 @@ public: #ifndef BOOST_NO_RVALUE_REFERENCES task_object( Fn && fn, allocator_t const& alloc) : task_base< void >(), - fn_( boost::forward( fn) ), alloc_( alloc) + fn_( forward< Fn >( fn) ), alloc_( alloc) {} #else task_object( Fn const& fn, allocator_t const& alloc) : @@ -95,7 +95,7 @@ public: task_object( BOOST_RV_REF( Fn) fn, allocator_t const& alloc) : task_base< void >(), - fn_( boost::forward( fn) ), alloc_( alloc) + fn_( fn), alloc_( alloc) {} #endif diff --git a/include/boost/fiber/future/future.hpp b/include/boost/fiber/future/future.hpp index 8024e9c4..e85a4037 100644 --- a/include/boost/fiber/future/future.hpp +++ b/include/boost/fiber/future/future.hpp @@ -762,12 +762,11 @@ public: } #ifndef BOOST_NO_RVALUE_REFERENCES - shared_future( future< R > && other) BOOST_NOEXCEPT : + shared_future( future< void > && other) BOOST_NOEXCEPT : future_() { //TODO: constructs a shared_future with the shared state of other using move semantics // after construction, other.valid() == false - swap( other); future_.swap( other.future_); } @@ -824,6 +823,12 @@ public: return * this; } + void swap( future< void > & other) BOOST_NOEXCEPT + { + //TODO: exchange the shared states of two shared_futures + future_.swap( other.future_); + } + void swap( shared_future & other) BOOST_NOEXCEPT { //TODO: exchange the shared states of two shared_futures diff --git a/include/boost/fiber/future/packaged_task.hpp b/include/boost/fiber/future/packaged_task.hpp index 34f16399..fba37619 100644 --- a/include/boost/fiber/future/packaged_task.hpp +++ b/include/boost/fiber/future/packaged_task.hpp @@ -83,7 +83,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, a) ); + ::new( a.allocate( 1) ) object_t( forward< task_fn >( fn), a) ); } template< typename Allocator > @@ -104,10 +104,9 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( fn, a) ); + ::new( a.allocate( 1) ) object_t( forward< task_fn >( fn), a) ); } #endif - template< typename Fn > explicit packaged_task( Fn && fn, typename disable_if< @@ -131,7 +130,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } template< typename Fn, typename Allocator > @@ -158,29 +157,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); - } - - packaged_task( packaged_task && other) BOOST_NOEXCEPT : - obtained_( false), - task_() - { - //TODO: constructs a std::packaged_task with thes - // shared state and task formerly owned by rhs, - // leaving rhs with no shared state and a moved-from task - swap( other); - } - - packaged_task & operator=( packaged_task && other) BOOST_NOEXCEPT - { - //TODO: releases the shared state, if any, destroys the - // previously-held task, and moves the shared state - // and the task owned by rhs into *this - // rhs is left without a shared state and with a - // moved-from task - packaged_task tmp( boost::move( other) ); - swap( tmp); - return * this; + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } #else template< typename Fn > @@ -253,7 +230,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( fn, a) ); } template< typename Fn, typename Allocator > @@ -274,8 +251,9 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( fn, a) ); } +#endif packaged_task( BOOST_RV_REF( packaged_task) other) BOOST_NOEXCEPT : obtained_( false), @@ -298,7 +276,6 @@ public: swap( tmp); return * this; } -#endif void swap( packaged_task & other) BOOST_NOEXCEPT { @@ -462,7 +439,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } template< typename Fn, typename Allocator > @@ -489,7 +466,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } packaged_task( packaged_task && other) BOOST_NOEXCEPT : @@ -584,7 +561,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } template< typename Fn, typename Allocator > @@ -605,7 +582,7 @@ public: typename object_t::allocator_t a( alloc); task_ = ptr_t( // placement new - ::new( a.allocate( 1) ) object_t( boost::forward< Fn >( fn), a) ); + ::new( a.allocate( 1) ) object_t( forward< Fn >( fn), a) ); } packaged_task( BOOST_RV_REF( packaged_task) other) BOOST_NOEXCEPT : diff --git a/include/boost/fiber/round_robin.hpp b/include/boost/fiber/round_robin.hpp index f6b914d1..3b6b41da 100644 --- a/include/boost/fiber/round_robin.hpp +++ b/include/boost/fiber/round_robin.hpp @@ -32,6 +32,48 @@ namespace boost { namespace fibers { +namespace detail { + +template< typename Allocator > +class main_notifier : public detail::notify +{ +public: + typedef typename Allocator::template rebind< + main_notifier< Allocator > + >::other allocator_t; + + main_notifier( allocator_t const& alloc) : + ready_( false), alloc_( alloc) + {} + + bool is_ready() const BOOST_NOEXCEPT + { + if ( ready_) + { + ready_ = false; + return true; + } + return false; + } + + void set_ready() BOOST_NOEXCEPT + { ready_ = true; } + + void deallocate_object() + { destroy_( alloc_, this); } + +private: + mutable bool ready_; + allocator_t alloc_; + + static void destroy_( allocator_t & alloc, main_notifier * p) + { + alloc.destroy( p); + alloc.deallocate( p, 1); + } +}; + +} class BOOST_FIBERS_DECL round_robin : public algorithm { diff --git a/include/boost/fiber/stack_context.hpp b/include/boost/fiber/stack_context.hpp index 529617d4..aed41652 100644 --- a/include/boost/fiber/stack_context.hpp +++ b/include/boost/fiber/stack_context.hpp @@ -11,7 +11,7 @@ #include -#include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX diff --git a/src/detail/scheduler.cpp b/src/detail/scheduler.cpp index ddb3bf34..5e4bb105 100644 --- a/src/detail/scheduler.cpp +++ b/src/detail/scheduler.cpp @@ -28,14 +28,14 @@ __thread algorithm * scheduler::instance_ = 0; #endif algorithm & -scheduler::instance() +scheduler::instance() BOOST_NOEXCEPT { BOOST_ASSERT( instance_); return * instance_; } algorithm * -scheduler::replace( algorithm * other) +scheduler::replace( algorithm * other) BOOST_NOEXCEPT { algorithm * old = instance_; instance_ = other; diff --git a/src/detail/segmented_stack_allocator.cpp b/src/detail/segmented_stack_allocator.cpp index 8f3a4f03..a0231d04 100644 --- a/src/detail/segmented_stack_allocator.cpp +++ b/src/detail/segmented_stack_allocator.cpp @@ -16,14 +16,14 @@ extern "C" { void *__splitstack_makecontext( std::size_t, - void * [BOOST_fiberS_SEGMENTS], + void * [BOOST_FIBERS_SEGMENTS], std::size_t *); -void __splitstack_releasecontext( void * [BOOST_fiberS_SEGMENTS]); +void __splitstack_releasecontext( void * [BOOST_FIBERS_SEGMENTS]); -void __splitstack_resetcontext( void * [BOOST_fiberS_SEGMENTS]); +void __splitstack_resetcontext( void * [BOOST_FIBERS_SEGMENTS]); -void __splitstack_block_signals_context( void * [BOOST_fiberS_SEGMENTS], +void __splitstack_block_signals_context( void * [BOOST_FIBERS_SEGMENTS], int * new_value, int * old_value); } diff --git a/src/fiber.cpp b/src/fiber.cpp index 53fc7607..bea8d9f7 100644 --- a/src/fiber.cpp +++ b/src/fiber.cpp @@ -29,7 +29,7 @@ fiber::start_fiber_() { detail::scheduler::instance().spawn( fiber_data_); } int -fiber::priority() const +fiber::priority() const BOOST_NOEXCEPT { BOOST_ASSERT( fiber_data_); @@ -37,7 +37,7 @@ fiber::priority() const } void -fiber::priority( int prio) +fiber::priority( int prio) BOOST_NOEXCEPT { BOOST_ASSERT( fiber_data_); @@ -72,7 +72,7 @@ fiber::join() } void -fiber::interrupt() +fiber::interrupt() BOOST_NOEXCEPT { BOOST_ASSERT( fiber_data_); diff --git a/src/future.cpp b/src/future.cpp index 834e4c1f..15c3283d 100755 --- a/src/future.cpp +++ b/src/future.cpp @@ -14,7 +14,7 @@ namespace fibers { class future_error_category : public system::error_category { public: - virtual const char* name() const + virtual const char* name() const BOOST_NOEXCEPT { return "future"; } virtual std::string message( int ev) const diff --git a/src/interruption.cpp b/src/interruption.cpp index 84f00d7e..968e74b2 100644 --- a/src/interruption.cpp +++ b/src/interruption.cpp @@ -24,27 +24,27 @@ namespace boost { namespace this_fiber { -disable_interruption::disable_interruption() : +disable_interruption::disable_interruption() BOOST_NOEXCEPT : set_( ( fibers::detail::scheduler::instance().active()->interruption_blocked() ) ) { if ( ! set_) fibers::detail::scheduler::instance().active()->interruption_blocked( true); } -disable_interruption::~disable_interruption() +disable_interruption::~disable_interruption() BOOST_NOEXCEPT { if ( ! set_) fibers::detail::scheduler::instance().active()->interruption_blocked( false); } -restore_interruption::restore_interruption( disable_interruption & disabler) : +restore_interruption::restore_interruption( disable_interruption & disabler) BOOST_NOEXCEPT : disabler_( disabler) { if ( ! disabler_.set_) fibers::detail::scheduler::instance().active()->interruption_blocked( false); } -restore_interruption::~restore_interruption() +restore_interruption::~restore_interruption() BOOST_NOEXCEPT { if ( ! disabler_.set_) fibers::detail::scheduler::instance().active()->interruption_blocked( true); diff --git a/src/round_robin.cpp b/src/round_robin.cpp index b70943b0..b91b6649 100644 --- a/src/round_robin.cpp +++ b/src/round_robin.cpp @@ -29,42 +29,22 @@ namespace boost { namespace fibers { -namespace detail { -class main_notifier : public detail::notify -{ -private: - mutable bool ready_; - -public: - main_notifier() : - ready_( false) - {} - - bool is_ready() const BOOST_NOEXCEPT - { - if ( ready_) - { - ready_ = false; - return true; - } - return false; - } - - void set_ready() BOOST_NOEXCEPT - { ready_ = true; } -}; - -} - -round_robin::round_robin() : +round_robin::round_robin() BOOST_NOEXCEPT : active_fiber_(), - notifier_( new detail::main_notifier() ), + notifier_(), wqueue_(), rqueue_() -{} +{ + typedef detail::main_notifier< std::allocator< round_robin > > notifier_t; + std::allocator< round_robin > alloc; + typename notifier_t::allocator_t a( alloc); + notifier_ = detail::notify::ptr_t( + // placement new + ::new( a.allocate( 1) ) notifier_t( a) ); +} -round_robin::~round_robin() +round_robin::~round_robin() BOOST_NOEXCEPT { #if 0 BOOST_ASSERT( ! active_fiber_);