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:
@@ -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;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user