2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-18 14:02:18 +00:00

allow different stack-allocators

This commit is contained in:
Oliver Kowalke
2014-02-26 19:40:28 +01:00
parent 12d97c57cd
commit 7cf2cabc99
7 changed files with 255 additions and 149 deletions

View File

@@ -13,9 +13,7 @@
#include <boost/assert.hpp>
#include <boost/atomic.hpp>
#include <boost/bind.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/all.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
@@ -42,8 +40,6 @@ namespace boost {
namespace fibers {
namespace detail {
namespace coro = boost::coroutines;
class BOOST_FIBERS_DECL fiber_base : public notify
{
public:
@@ -81,50 +77,18 @@ private:
fss_data_t fss_data_;
// set terminate is only set inside fiber_base::trampoline_()
void set_terminated_() BOOST_NOEXCEPT;
void trampoline_( coro::symmetric_coroutine< void >::yield_type &);
protected:
atomic< state_t > state_;
atomic< int > flags_;
atomic< int > priority_;
coro::symmetric_coroutine< void >::yield_type * callee_;
coro::symmetric_coroutine< void >::call_type caller_;
exception_ptr except_;
spinlock splk_;
std::vector< ptr_t > waiting_;
atomic< state_t > state_;
atomic< int > flags_;
atomic< int > priority_;
exception_ptr except_;
spinlock splk_;
std::vector< ptr_t > waiting_;
void release();
virtual void run() = 0;
public:
template< typename StackAllocator, typename Allocator >
fiber_base( attributes const& attrs, StackAllocator const& stack_alloc, Allocator const&) :
fss_data_(),
state_( READY),
flags_( 0),
priority_( 0),
callee_( 0),
caller_(
boost::bind( & fiber_base::trampoline_, this, _1),
attrs,
stack_alloc),
except_(),
waiting_()
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( 0 == callee_);
caller_(); // jump to trampoline
BOOST_ASSERT( 0 != callee_);
BOOST_ASSERT( * callee_);
set_ready(); // fiber is setup and now ready to run
}
fiber_base();
virtual ~fiber_base();
@@ -137,10 +101,6 @@ public:
void priority( int prio) BOOST_NOEXCEPT
{ priority_ = prio; }
void resume();
void suspend();
bool join( ptr_t const&);
bool interruption_blocked() const BOOST_NOEXCEPT
@@ -170,6 +130,8 @@ public:
bool is_waiting() const BOOST_NOEXCEPT
{ return WAITING == state_; }
void set_terminated() BOOST_NOEXCEPT;
void set_ready() BOOST_NOEXCEPT;
void set_running() BOOST_NOEXCEPT;
@@ -188,6 +150,10 @@ public:
{ return except_; }
void rethrow() const;
virtual void resume() = 0;
virtual void suspend() = 0;
};
}}}

View File

@@ -10,13 +10,17 @@
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/bind.hpp>
#include <boost/config.hpp>
#include <boost/coroutine/all.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/move/move.hpp>
#include <boost/ref.hpp>
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/exceptions.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -31,19 +35,26 @@ namespace boost {
namespace fibers {
namespace detail {
template< typename Fn, typename Allocator >
namespace coro = boost::coroutines;
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object : public fiber_base
{
public:
typedef typename Allocator::template rebind<
fiber_object< Fn, Allocator >
>::other allocator_t;
fiber_object< Fn, StackAllocator, Allocator >
>::other allocator_t;
private:
typedef fiber_base base_type;
typedef fiber_base base_t;
typedef coro::symmetric_coroutine<
void, StackAllocator
> coro_t;
Fn fn_;
allocator_t alloc_;
Fn fn_;
typename coro_t::yield_type * callee_;
typename coro_t::call_type caller_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
@@ -54,41 +65,131 @@ private:
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void trampoline_( typename coro_t::yield_type & yield)
{
BOOST_ASSERT( yield);
BOOST_ASSERT( ! is_terminated() );
callee_ = & yield;
set_running();
suspend();
try
{
BOOST_ASSERT( is_running() );
fn_();
BOOST_ASSERT( is_running() );
}
catch ( coro::detail::forced_unwind const&)
{
set_terminated();
release();
throw;
}
catch ( fiber_interrupted const&)
{ except_ = current_exception(); }
catch (...)
{ std::terminate(); }
set_terminated();
release();
suspend();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}
public:
#ifndef BOOST_NO_RVALUE_REFERENCES
template< typename StackAllocator >
fiber_object( Fn && fn, attributes const& attr,
fiber_object( Fn && fn, attributes const& attrs,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type( attr, stack_alloc, alloc),
base_t(),
fn_( forward< Fn >( fn) ),
callee_( 0),
caller_(
boost::bind( & fiber_object::trampoline_, this, _1),
attrs,
stack_alloc),
alloc_( alloc)
{}
#else
template< typename StackAllocator >
fiber_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type( attr, stack_alloc, alloc),
fn_( fn),
alloc_( alloc)
{}
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( 0 == callee_);
template< typename StackAllocator >
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
caller_(); // jump to trampoline
BOOST_ASSERT( 0 != callee_);
BOOST_ASSERT( * callee_);
set_ready(); // fiber is setup and now ready to run
}
#else
fiber_object( Fn fn, attributes const& attrs,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_type( attr, stack_alloc, alloc),
base_t(),
fn_( fn),
callee_( 0),
caller_(
boost::bind( & fiber_object::trampoline_, this, _1),
attrs,
stack_alloc),
alloc_( alloc)
{}
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( 0 == callee_);
caller_(); // jump to trampoline
BOOST_ASSERT( 0 != callee_);
BOOST_ASSERT( * callee_);
set_ready(); // fiber is setup and now ready to run
}
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attrs,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
base_t(),
fn_( fn),
callee_( 0),
caller_(
boost::bind( & fiber_object::trampoline_, this, _1),
attrs,
stack_alloc),
alloc_( alloc)
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( 0 == callee_);
caller_(); // jump to trampoline
BOOST_ASSERT( 0 != callee_);
BOOST_ASSERT( * callee_);
set_ready(); // fiber is setup and now ready to run
}
#endif
void deallocate_object()
{ destroy_( alloc_, this); }
void run()
{ fn_(); }
void resume()
{
BOOST_ASSERT( caller_);
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
caller_();
}
void suspend()
{
BOOST_ASSERT( callee_);
BOOST_ASSERT( * callee_);
( * callee_)();
BOOST_ASSERT( is_running() ); // set by the scheduler-algorithm
}
};
}}}

View File

@@ -77,7 +77,7 @@ public:
impl_()
{
typedef detail::fiber_object<
fiber_fn, std::allocator< fiber >
fiber_fn, stack_allocator, std::allocator< fiber >
> object_t;
object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -93,7 +93,7 @@ public:
impl_()
{
typedef detail::fiber_object<
fiber_fn, std::allocator< fiber >
fiber_fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -109,7 +109,7 @@ public:
impl_()
{
typedef detail::fiber_object<
fiber_fn, Allocator
fiber_fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -125,7 +125,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -141,7 +141,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -157,7 +157,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, Allocator
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -173,7 +173,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -189,7 +189,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -205,7 +205,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, Allocator
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -221,7 +221,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -237,7 +237,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, std::allocator< fiber >
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
@@ -253,7 +253,7 @@ public:
impl_()
{
typedef detail::fiber_object<
Fn, Allocator
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(