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

modification for fiberswq

This commit is contained in:
Oliver Kowalke
2012-11-22 18:57:59 +01:00
parent 5f256a5d17
commit c9969ebdaf
13 changed files with 583 additions and 282 deletions

View File

@@ -4,8 +4,8 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_DETAIL_STRATUM_BASE_H
#define BOOST_FIBERS_DETAIL_STRATUM_BASE_H
#ifndef BOOST_FIBERS_DETAIL_FIBER_BASE_H
#define BOOST_FIBERS_DETAIL_FIBER_BASE_H
#include <cstddef>
#include <iostream>
@@ -15,12 +15,13 @@
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/context/stack_allocator.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -30,63 +31,28 @@ namespace boost {
namespace fibers {
namespace detail {
struct forced_unwind {};
enum flag_t
{
flag_resumed = 1 << 1,
flag_complete = 1 << 2,
flag_unwind_stack = 1 << 3,
flag_canceled = 1 << 4
};
template< typename Fiber >
void trampoline( intptr_t vp)
{
BOOST_ASSERT( vp);
Fiber * f( reinterpret_cast< Fiber * >( vp) );
BOOST_ASSERT( ! f->is_complete() );
BOOST_ASSERT( f->is_resumed() );
try
{ f->exec(); }
catch ( forced_unwind const&)
{}
catch (...)
{
//TODO: call std::terminate() or do nothing?
}
f->flags_ &= ~flag_resumed;
f->flags_ &= ~flag_unwind_stack;
f->flags_ |= flag_complete;
ctx::jump_fcontext( & f->callee_, & f->caller_, 0, f->preserve_fpu_);
}
class BOOST_FIBERS_DECL fiber_base : private noncopyable
{
public:
typedef intrusive_ptr< fiber_base > ptr_t;
private:
template< typename T >
friend void trampoline( intptr_t);
friend class scheduler;
template< typename X, typename Y, typename Z >
friend class fiber_object;
std::size_t use_count_;
ctx::stack_allocator alloc_;
ctx::fcontext_t caller_;
ctx::fcontext_t callee_;
context::fcontext_t caller_;
context::fcontext_t * callee_;
int flags_;
bool preserve_fpu_;
exception_ptr except_;
std::vector< ptr_t > joining_;
void unwind_stack_();
void terminate_();
void notify_();
protected:
virtual void deallocate_object() = 0;
public:
class id
{
@@ -95,31 +61,31 @@ public:
fiber_base::ptr_t impl_;
id( fiber_base::ptr_t const& impl) :
explicit id( fiber_base::ptr_t const& impl) BOOST_NOEXCEPT :
impl_( impl)
{}
public:
id() :
id() BOOST_NOEXCEPT :
impl_()
{}
bool operator==( id const& other) const
bool operator==( id const& other) const BOOST_NOEXCEPT
{ return impl_ == other.impl_; }
bool operator!=( id const& other) const
bool operator!=( id const& other) const BOOST_NOEXCEPT
{ return impl_ != other.impl_; }
bool operator<( id const& other) const
bool operator<( id const& other) const BOOST_NOEXCEPT
{ return impl_ < other.impl_; }
bool operator>( id const& other) const
bool operator>( id const& other) const BOOST_NOEXCEPT
{ return other.impl_ < impl_; }
bool operator<=( id const& other) const
bool operator<=( id const& other) const BOOST_NOEXCEPT
{ return ! ( * this > other); }
bool operator>=( id const& other) const
bool operator>=( id const& other) const BOOST_NOEXCEPT
{ return ! ( * this < other); }
template< typename charT, class traitsT >
@@ -132,26 +98,23 @@ public:
return os << "{not-valid}";
}
operator bool() const
operator bool() const BOOST_NOEXCEPT
{ return 0 != impl_; }
bool operator!() const
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_; }
};
fiber_base( std::size_t size, bool preserve_fpu);
fiber_base( context::fcontext_t *, bool, bool);
virtual ~fiber_base();
virtual ~fiber_base() {}
id get_id() const;
virtual void terminate() = 0;
bool is_canceled() const;
id get_id() const BOOST_NOEXCEPT
{ return id( ptr_t( const_cast< fiber_base * >( this) ) ); }
bool is_complete() const;
bool is_resumed() const;
void join( ptr_t const& p);
void join( ptr_t const&);
void resume();
@@ -165,13 +128,29 @@ public:
void sleep( chrono::system_clock::time_point const& abs_time);
virtual void exec() = 0;
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_forced_unwind); }
friend inline void intrusive_ptr_add_ref( fiber_base * p)
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool preserve_fpu() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_preserve_fpu); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
bool is_canceled() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_canceled); }
bool is_resumed() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_resumed); }
friend inline void intrusive_ptr_add_ref( fiber_base * p) BOOST_NOEXCEPT
{ ++p->use_count_; }
friend inline void intrusive_ptr_release( fiber_base * p)
{ if ( --p->use_count_ == 0) delete p; }
{ if ( --p->use_count_ == 0) p->deallocate_object(); }
};
}}}
@@ -180,4 +159,4 @@ public:
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_STRATUM_BASE_H
#endif // BOOST_FIBERS_DETAIL_FIBER_BASE_H

View File

@@ -4,17 +4,22 @@
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H
#define BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H
#ifndef BOOST_FIBERS_DETAIL_FIBER_OBJECT_H
#define BOOST_FIBERS_DETAIL_FIBER_OBJECT_H
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.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/detail/flags.hpp>
#include <boost/fiber/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -24,66 +29,291 @@ namespace boost {
namespace fibers {
namespace detail {
template< typename Fn >
struct forced_unwind {};
template< typename Fiber >
void trampoline( intptr_t vp)
{
BOOST_ASSERT( vp);
Fiber * f( reinterpret_cast< Fiber * >( vp) );
f->exec();
}
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object : public fiber_base
{
private:
Fn fn_;
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() );
if ( this->except_) rethrow_exception( this->except_);
}
void unwind_stack_()
{
}
public:
fiber_object( Fn fn, std::size_t size, bool preserve_fpu) :
fiber_base( size, preserve_fpu),
fn_( fn)
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#else
fiber_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
fiber_object( BOOST_RV_REF( Fn) fn, std::size_t size, bool preserve_fpu) :
fiber_base( size, preserve_fpu),
fn_( boost::move( fn) )
{}
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#endif
void exec()
{ fn_(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
void terminate()
{
BOOST_ASSERT( ! is_resumed() );
if ( ! is_complete() )
{
flags_ |= flag_canceled;
unwind_stack_();
}
notify_();
BOOST_ASSERT( is_complete() );
BOOST_ASSERT( ! is_resumed() );
BOOST_ASSERT( joining_.empty() );
}
};
template< typename Fn >
class fiber_object< reference_wrapper< Fn > > : public fiber_base
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object< reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base
{
private:
Fn fn_;
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() );
if ( this->except_) rethrow_exception( this->except_);
}
public:
fiber_object( reference_wrapper< Fn > fn, std::size_t size, bool preserve_fpu) :
fiber_base( size, preserve_fpu),
fn_( fn)
{}
fiber_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
void exec()
{ fn_(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
template< typename Fn >
class fiber_object< const reference_wrapper< Fn > > : public fiber_base
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object< const reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base
{
private:
Fn fn_;
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
context::jump_fcontext(
& this->caller_, this->callee_,
reinterpret_cast< intptr_t >( this),
this->preserve_fpu() );
if ( this->except_) rethrow_exception( this->except_);
}
public:
fiber_object( const reference_wrapper< Fn > fn, std::size_t size, bool preserve_fpu) :
fiber_base( size, preserve_fpu),
fn_( fn)
{}
fiber_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
void exec()
{ fn_(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
}}}
@@ -92,4 +322,4 @@ public:
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_STRATUM_OBJECT_H
#endif // BOOST_FIBERS_DETAIL_FIBER_OBJECT_H

View File

@@ -0,0 +1,38 @@
// 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)
#ifndef BOOST_FIBERS_DETAIL_FLAGS_H
#define BOOST_FIBERS_DETAIL_FLAGS_H
#include <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
enum flag_t
{
flag_forced_unwind = 1 << 1,
flag_unwind_stack = 1 << 2,
flag_preserve_fpu = 1 << 3,
flag_complete = 1 << 4,
flag_resumed = 1 << 5,
flag_canceled = 1 << 6
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_FLAGS_H

View File

@@ -92,25 +92,7 @@ private:
public:
static scheduler & instance();
template< typename Fn >
fiber spawn( Fn fn, std::size_t size, bool preserve_fpu)
{
fiber f( fn, size, preserve_fpu);
active_fiber_.swap( f.impl_);
resume_();
active_fiber_.swap( f.impl_);
return f;
}
template< typename Fn >
fiber spawn( BOOST_RV_REF( Fn) fn, std::size_t size, bool preserve_fpu)
{
fiber f( boost::move( fn), size, preserve_fpu);
active_fiber_.swap( f.impl_);
resume_();
active_fiber_.swap( f.impl_);
return f;
}
void spawn( fiber_base::ptr_t const&);
void join( fiber_base::ptr_t const&);

View File

@@ -11,9 +11,13 @@
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/stack_utils.hpp>
#include <boost/move/move.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/fiber_object.hpp>
@@ -45,68 +49,130 @@ private:
friend void migrate_to( BOOST_RV_REF( fiber) );
friend class detail::scheduler;
struct dummy
{ void nonnull() {} };
typedef detail::fiber_base base_t;
typedef base_t::ptr_t ptr_t;
typedef void ( dummy::*safe_bool)();
ptr_t impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( fiber);
fiber( ptr_t const& impl) :
fiber( ptr_t const& impl) BOOST_NOEXCEPT :
impl_( impl)
{ BOOST_ASSERT( impl_); }
template< typename Fn >
fiber( Fn fn, std::size_t size = ctx::default_stacksize(),
bool preserve_fpu = true) :
impl_(
new detail::fiber_object< Fn >(
fn, size, preserve_fpu) )
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_MSVC
typedef void ( * fiber_fn)();
template< typename Fn >
fiber( BOOST_RV_REF( Fn) fn, std::size_t size = ctx::default_stacksize(),
bool preserve_fpu = true) :
impl_(
new detail::fiber_object< Fn >(
boost::move( fn), size, preserve_fpu) )
{}
template< typename StackAllocator, typename Allocator >
explicit fiber( fiber_fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocacator const& alloc) :
impl_()
{
typedef detail::fiber_object<
fiber_fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a) );
}
#endif
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocacator const& alloc,
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
}
#else
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc,
typename disable_if<
is_convertible< Fn &, BOOST_RV_REF( Fn) >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
}
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc,
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
}
#endif
public:
typedef detail::fiber_base::id id;
typedef void ( * unspecified_bool_type)( fiber ***);
static void unspecified_bool( fiber ***) {}
fiber() :
fiber() BOOST_NOEXCEPT :
impl_()
{}
fiber( BOOST_RV_REF( fiber) other) :
fiber( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT :
impl_()
{ impl_.swap( other.impl_); }
{ swap( other); }
fiber & operator=( BOOST_RV_REF( fiber) other)
fiber & operator=( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT
{
fiber tmp( other);
fiber tmp( move( other) );
swap( tmp);
return * this;
}
operator unspecified_bool_type() const;
operator safe_bool() const BOOST_NOEXCEPT
{ return ( empty() || impl_->is_complete() ) ? 0 : & dummy::nonnull; }
bool operator!() const;
bool operator!() const BOOST_NOEXCEPT
{ return empty() || impl_->is_complete(); }
void swap( fiber & other);
void swap( fiber & other) BOOST_NOEXCEPT
{ impl_.swap( other.impl_); }
bool operator==( fiber const& other) const;
bool operator!=( fiber const& other) const;
bool empty() const BOOST_NOEXCEPT
{ return ! impl_; }
id get_id() const;
bool is_joinable() const;
bool is_complete() const;
id get_id() const BOOST_NOEXCEPT
{ return impl_ ? impl_->get_id() : id(); }
void cancel();

27
boost/fiber/flags.hpp Normal file
View File

@@ -0,0 +1,27 @@
// 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)
#ifndef BOOST_FIBERS_FLAGS_H
#define BOOST_FIBERS_FLAGS_H
namespace boost {
namespace fibers {
enum flag_unwind_t
{
stack_unwind = 0,
no_stack_unwind
};
enum flag_fpu_t
{
fpu_preserved = 0,
fpu_not_preserved
};
}}
#endif // BOOST_FIBERS_FLAGS_H

View File

@@ -6,10 +6,11 @@
#ifndef BOOST_THIS_STRATUM_OPERATIONS_H
#define BOOST_THIS_STRATUM_OPERATIONS_H
#include <memory>
#include <boost/assert.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/context/stack_utils.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
@@ -66,15 +67,70 @@ void yield_break()
namespace fibers {
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_MSVC
#endif
#else
template< typename Fn >
fiber spawn( Fn fn, std::size_t size = ctx::default_stacksize(),
bool preserve_fpu = true)
{ return detail::scheduler::instance().spawn( fn, size, preserve_fpu); }
fiber spawn( Fn fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >() )
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
template< typename Fn, typename StackAllocator >
fiber spawn( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >() )
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
template< typename Fn, typename StackAllocator, typename Allocator >
fiber spawn( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc)
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
template< typename Fn >
fiber spawn( BOOST_RV_REF( Fn) fn, std::size_t size = ctx::default_stacksize(),
bool preserve_fpu = true)
{ return detail::scheduler::instance().spawn( boost::move( fn), size, preserve_fpu); }
fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >() )
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
template< typename Fn, typename StackAllocator >
fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >() )
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
template< typename Fn, typename StackAllocator, typename Allocator >
fiber spawn( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc)
{
fiber f( fn, attr, stack_alloc, alloc);
detail::scheduler::instance().spawn( f.impl_);
return f;
}
#endif
inline
bool run()
@@ -87,17 +143,17 @@ bool run()
BOOST_PP_ENUM(n,BOOST_FIBERS_WAITFOR_STRATUM_FN_ARG,~)
#define BOOST_FIBERS_WAITFOR_STRATUM_AND(z,n,t) \
BOOST_PP_EXPR_IF(n,&&) BOOST_PP_CAT(s,n).is_complete()
BOOST_PP_EXPR_IF(n,&&) BOOST_PP_CAT(s,n)
#define BOOST_FIBERS_WAITFOR_STRATUM_OR(z,n,t) \
BOOST_PP_EXPR_IF(n,||) BOOST_PP_CAT(s,n).is_complete()
BOOST_PP_EXPR_IF(n,||) BOOST_PP_CAT(s,n)
#define BOOST_FIBERS_WAITFOR_STRATUM_CANCEL(z,n,t) \
if ( ! BOOST_PP_CAT(s,n).is_complete() ) \
if ( ! BOOST_PP_CAT(s,n) ) \
BOOST_PP_CAT(s,n).cancel();
#define BOOST_FIBERS_WAITFOR_STRATUM_READY(z,n,t) \
if ( BOOST_PP_CAT(s,n).is_complete() ) return n;
if ( BOOST_PP_CAT(s,n) ) return n;
#define BOOST_FIBERS_WAITFOR_STRATUM_ALL(z,n,unused) \
inline \

View File

@@ -16,7 +16,7 @@
#endif
namespace boost {
namespace coroutines {
namespace fibers {
using detail::stack_allocator;
}}

View File

@@ -29,11 +29,11 @@ exe asio/host
: asio/host.cpp
;
exe barrier : barrier.cpp ;
exe future : future.cpp ;
exe join : join.cpp ;
exe ping_pong : ping_pong.cpp ;
#exe barrier : barrier.cpp ;
#exe future : future.cpp ;
#exe join : join.cpp ;
#exe ping_pong : ping_pong.cpp ;
exe simple : simple.cpp ;
exe wait_all : wait_all.cpp ;
exe wait_any : wait_any.cpp ;
exe wait_any_cancel : wait_any_cancel.cpp ;
#exe wait_all : wait_all.cpp ;
#exe wait_any : wait_any.cpp ;
#exe wait_any_cancel : wait_any_cancel.cpp ;

View File

@@ -26,7 +26,7 @@ int main()
stm::fiber s1( stm::spawn( boost::bind( fn, "abc", 5) ) );
stm::fiber s2( stm::spawn( boost::bind( fn, "xyz", 7) ) );
while ( ! s1.is_complete() || ! s2.is_complete() )
while ( s1 || s2 )
stm::run();
std::cout << "done." << std::endl;

View File

@@ -20,37 +20,6 @@ namespace boost {
namespace fibers {
namespace detail {
void
fiber_base::unwind_stack_()
{
BOOST_ASSERT( ! is_complete() );
BOOST_ASSERT( ! is_resumed() );
flags_ |= flag_resumed;
flags_ |= flag_unwind_stack;
ctx::jump_fcontext( & caller_, & callee_, 0, preserve_fpu_);
BOOST_ASSERT( is_complete() );
BOOST_ASSERT( ! is_resumed() );
}
void
fiber_base::terminate_()
{
BOOST_ASSERT( ! is_resumed() );
if ( ! is_complete() )
{
flags_ |= flag_canceled;
unwind_stack_();
}
notify_();
BOOST_ASSERT( is_complete() );
BOOST_ASSERT( ! is_resumed() );
BOOST_ASSERT( joining_.empty() );
}
void
fiber_base::notify_()
{
@@ -62,43 +31,18 @@ fiber_base::notify_()
joining_.clear();
}
fiber_base::fiber_base( std::size_t size, bool preserve_fpu) :
fiber_base::fiber_base( context::fcontext_t * callee, bool unwind, bool preserve_fpu) :
use_count_( 0),
alloc_(),
caller_(),
callee_(),
callee_( callee),
flags_( 0),
preserve_fpu_( preserve_fpu),
except_(),
joining_()
{
callee_.fc_stack.base = alloc_.allocate( size);
callee_.fc_stack.size = size;
ctx::make_fcontext( & callee_, trampoline< fiber_base >);
if ( unwind) flags_ |= flag_forced_unwind;
if ( preserve_fpu) flags_ |= flag_preserve_fpu;
}
fiber_base::~fiber_base()
{
terminate_();
alloc_.deallocate( callee_.fc_stack.base, callee_.fc_stack.size);
}
fiber_base::id
fiber_base::get_id() const
{ return id( ptr_t( const_cast< fiber_base * >( this) ) ); }
bool
fiber_base::is_canceled() const
{ return 0 != ( flags_ & flag_canceled); }
bool
fiber_base::is_complete() const
{ return 0 != ( flags_ & flag_complete); }
bool
fiber_base::is_resumed() const
{ return 0 != ( flags_ & flag_resumed); }
void
fiber_base::join( ptr_t const& p)
{
@@ -116,7 +60,7 @@ fiber_base::resume()
BOOST_ASSERT( ! is_resumed() );
flags_ |= flag_resumed;
ctx::jump_fcontext( & caller_, & callee_, ( intptr_t) this, preserve_fpu_);
context::jump_fcontext( & caller_, callee_, ( intptr_t) this, preserve_fpu() );
if ( is_complete() ) notify_();
@@ -130,7 +74,7 @@ fiber_base::suspend()
BOOST_ASSERT( is_resumed() );
flags_ &= ~flag_resumed;
ctx::jump_fcontext( & callee_, & caller_, 0, preserve_fpu_);
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT( is_resumed() );

View File

@@ -58,6 +58,19 @@ scheduler::instance()
return * static_local.get();
}
void
scheduler::spawn( fiber_base::ptr_t const& f)
{
BOOST_ASSERT( f);
BOOST_ASSERT( ! f->is_complete() );
BOOST_ASSERT( f != active_fiber_);
fiber_base::ptr_t tmp = active_fiber_;
active_fiber_ = f;
resume_();
active_fiber_ = tmp;
}
void
scheduler::join( fiber_base::ptr_t const& f)
{
@@ -98,7 +111,7 @@ scheduler::cancel( fiber_base::ptr_t const& f)
// terminate fiber means unwinding its stack
// so it becomes complete and joining strati
// will be notified
active_fiber_->terminate_();
active_fiber_->terminate();
active_fiber_ = tmp;
// erase completed fiber from waiting-queue
f_idx_.erase( f);

View File

@@ -20,40 +20,6 @@
namespace boost {
namespace fibers {
fiber::operator unspecified_bool_type() const
{ return impl_ ? unspecified_bool : 0; }
bool
fiber::operator!() const
{ return ! impl_; }
bool
fiber::operator==( fiber const& other) const
{ return get_id() == other.get_id(); }
bool
fiber::operator!=( fiber const& other) const
{ return ! ( get_id() == other.get_id() ); }
void
fiber::swap( fiber & other)
{ impl_.swap( other.impl_); }
fiber::id
fiber::get_id() const
{ return impl_ ? impl_->get_id() : id(); }
bool
fiber::is_joinable() const
{ return impl_ && ! impl_->is_complete(); }
bool
fiber::is_complete() const
{
BOOST_ASSERT( impl_);
return impl_->is_complete();
}
void
fiber::cancel()
{