mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-20 02:32:19 +00:00
fiber removed
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
|
||||
// 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_FIBER_H
|
||||
#define BOOST_FIBER_H
|
||||
|
||||
#include <boost/fiber/asym_fiber.hpp>
|
||||
#include <boost/fiber/exceptions.hpp>
|
||||
#include <boost/fiber/sym_fiber.hpp>
|
||||
|
||||
#endif // BOOST_FIBER_H
|
||||
@@ -1,228 +0,0 @@
|
||||
|
||||
// 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_ASYM_FIBER_H
|
||||
#define BOOST_FIBERS_ASYM_FIBER_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/asym_fiber_base.hpp>
|
||||
#include <boost/fiber/detail/asym_fiber_object.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4251)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
class BOOST_FIBER_DECL asym_fiber
|
||||
{
|
||||
private:
|
||||
struct dummy {};
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE( asym_fiber);
|
||||
|
||||
detail::asym_fiber_base::ptr impl_;
|
||||
|
||||
static detail::asym_fiber_base::ptr make_fiber_(
|
||||
void( * fn)(), std::size_t stacksize, bool do_return)
|
||||
{
|
||||
return detail::asym_fiber_base::ptr(
|
||||
do_return
|
||||
? new detail::asym_fiber_object< void(*)() >( fn, stacksize, detail::asym_fiber_base::do_return)
|
||||
: new detail::asym_fiber_object< void(*)() >( fn, stacksize, detail::asym_fiber_base::do_not_return) );
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
template< typename Fn >
|
||||
static detail::asym_fiber_base::ptr make_fiber_(
|
||||
Fn & fn, std::size_t stacksize, bool do_return)
|
||||
{
|
||||
return detail::asym_fiber_base::ptr(
|
||||
do_return
|
||||
? new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_return)
|
||||
: new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_not_return) );
|
||||
}
|
||||
#else
|
||||
template< typename Fn >
|
||||
static detail::asym_fiber_base::ptr make_fiber_(
|
||||
Fn fn, std::size_t stacksize, bool do_return)
|
||||
{
|
||||
return detail::asym_fiber_base::ptr(
|
||||
do_return
|
||||
? new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_return)
|
||||
: new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_not_return) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template< typename Fn >
|
||||
static detail::asym_fiber_base::ptr make_fiber__(
|
||||
BOOST_RV_REF( Fn) fn, std::size_t stacksize, bool do_return)
|
||||
{
|
||||
return detail::asym_fiber_base::ptr(
|
||||
do_return
|
||||
? new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_return)
|
||||
: new detail::asym_fiber_object< Fn >( fn, stacksize, detail::asym_fiber_base::do_not_return) );
|
||||
}
|
||||
|
||||
public:
|
||||
static std::size_t max_stacksize;
|
||||
static std::size_t min_stacksize;
|
||||
static std::size_t default_stacksize;
|
||||
|
||||
class id;
|
||||
|
||||
asym_fiber();
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
template< typename Fn >
|
||||
asym_fiber( Fn & fn, std::size_t stacksize, bool do_return = true) :
|
||||
impl_( make_fiber_( fn, stacksize, do_return) )
|
||||
{}
|
||||
#else
|
||||
template< typename Fn >
|
||||
asym_fiber( Fn fn, std::size_t stacksize, bool do_return = true) :
|
||||
impl_( make_fiber_( fn, stacksize, do_return) )
|
||||
{}
|
||||
#endif
|
||||
|
||||
template< typename Fn >
|
||||
asym_fiber( BOOST_RV_REF( Fn) fn, std::size_t stacksize, bool do_return = true) :
|
||||
impl_( make_fiber__( fn, stacksize, do_return) )
|
||||
{}
|
||||
|
||||
#define BOOST_FIBERS_ASYM_FIBER_ARG(z, n, unused) \
|
||||
BOOST_PP_CAT(A, n) BOOST_PP_CAT(a, n)
|
||||
#define BOOST_ENUM_FIBERS_ASYM_FIBER_ARGS(n) BOOST_PP_ENUM(n, BOOST_FIBERS_ASYM_FIBER_ARG, ~)
|
||||
|
||||
#define BOOST_FIBERS_ASYM_FIBER_CTOR(z, n, unused) \
|
||||
template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
||||
asym_fiber( Fn fn, BOOST_ENUM_FIBERS_ASYM_FIBER_ARGS(n), std::size_t stacksize, bool do_return = true) : \
|
||||
impl_( \
|
||||
make_fiber_( \
|
||||
boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
|
||||
stacksize, do_return) ) \
|
||||
{} \
|
||||
|
||||
#ifndef BOOST_FIBERS_ASYM_MAX_ARITY
|
||||
#define BOOST_FIBERS_ASYM_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_FIBERS_ASYM_MAX_ARITY, BOOST_FIBERS_ASYM_FIBER_CTOR, ~)
|
||||
|
||||
#undef BOOST_FIBERS_ASYM_MAY_ARITY
|
||||
#undef BOOST_FIBERS_ASYM_FIBER_ARG
|
||||
#undef BOOST_FIBERS_ASYM_FIBER_ARGS
|
||||
#undef BOOST_FIBERS_ASYM_FIBER_CTOR
|
||||
|
||||
asym_fiber( asym_fiber const& other);
|
||||
|
||||
asym_fiber & operator=( BOOST_COPY_ASSIGN_REF( asym_fiber) other);
|
||||
|
||||
asym_fiber( BOOST_RV_REF( asym_fiber) other);
|
||||
|
||||
asym_fiber & operator=( BOOST_RV_REF( asym_fiber) other);
|
||||
|
||||
typedef detail::asym_fiber_base::ptr::unspecified_bool_type unspecified_bool_type;
|
||||
|
||||
operator unspecified_bool_type() const;
|
||||
|
||||
bool operator!() const;
|
||||
|
||||
void swap( asym_fiber & other);
|
||||
|
||||
id get_id() const;
|
||||
|
||||
bool operator==( asym_fiber const& other) const;
|
||||
bool operator!=( asym_fiber const& other) const;
|
||||
|
||||
void run();
|
||||
|
||||
void yield();
|
||||
|
||||
bool finished() const;
|
||||
};
|
||||
|
||||
class BOOST_FIBER_DECL asym_fiber::id
|
||||
{
|
||||
private:
|
||||
friend class asym_fiber;
|
||||
|
||||
boost::uint64_t id_;
|
||||
|
||||
explicit id( detail::asym_fiber_base::ptr const& info) :
|
||||
id_( reinterpret_cast< boost::uint64_t >( info.get() ) )
|
||||
{}
|
||||
|
||||
public:
|
||||
id() :
|
||||
id_( 0)
|
||||
{}
|
||||
|
||||
bool operator==( id const& other) const
|
||||
{ return id_ == other.id_; }
|
||||
|
||||
bool operator!=( id const& other) const
|
||||
{ return id_ != other.id_; }
|
||||
|
||||
bool operator<( id const& other) const
|
||||
{ return id_ < other.id_; }
|
||||
|
||||
bool operator>( id const& other) const
|
||||
{ return other.id_ < id_; }
|
||||
|
||||
bool operator<=( id const& other) const
|
||||
{ return !( other.id_ < id_); }
|
||||
|
||||
bool operator>=( id const& other) const
|
||||
{ return ! ( id_ < other.id_); }
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, id const& other)
|
||||
{
|
||||
if ( 0 != other.id_) return os << other.id_;
|
||||
else return os << "{not-a-fiber}";
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( asym_fiber & l, asym_fiber & r)
|
||||
{ return l.swap( r); }
|
||||
|
||||
}
|
||||
|
||||
using fibers::asym_fiber;
|
||||
|
||||
}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_ASYM_FIBER_H
|
||||
@@ -1,92 +0,0 @@
|
||||
|
||||
// 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_ASYM_FIBER_BASE_H
|
||||
#define BOOST_FIBERS_DETAIL_ASYM_FIBER_BASE_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <stack>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/all.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4251)
|
||||
#pragma warning(disable:4275)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
namespace detail {
|
||||
|
||||
BOOST_FIBER_DECL void trampoline_asym( void *);
|
||||
|
||||
class BOOST_FIBER_DECL asym_fiber_base : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef intrusive_ptr< asym_fiber_base > ptr;
|
||||
|
||||
struct do_not_return_t {};
|
||||
|
||||
struct do_return_t {};
|
||||
|
||||
static do_not_return_t do_not_return;
|
||||
static do_return_t do_return;
|
||||
|
||||
friend BOOST_FIBER_DECL void trampoline_asym( void * vp);
|
||||
|
||||
friend inline void intrusive_ptr_add_ref( asym_fiber_base * p)
|
||||
{ ++p->use_count_; }
|
||||
|
||||
friend inline void intrusive_ptr_release( asym_fiber_base * p)
|
||||
{ if ( --p->use_count_ == 0) delete p; }
|
||||
|
||||
asym_fiber_base( std::size_t stacksize, do_not_return_t);
|
||||
|
||||
asym_fiber_base( std::size_t stacksize, do_return_t);
|
||||
|
||||
virtual ~asym_fiber_base() {}
|
||||
|
||||
void run();
|
||||
|
||||
void yield();
|
||||
|
||||
void set_finished();
|
||||
|
||||
bool get_finished() const;
|
||||
|
||||
protected:
|
||||
virtual void exec() = 0;
|
||||
|
||||
private:
|
||||
unsigned int use_count_;
|
||||
bool finished_;
|
||||
context<> caller_;
|
||||
context<> callee_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_ASYM_FIBER_BASE_H
|
||||
@@ -1,125 +0,0 @@
|
||||
|
||||
// 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_ASYM_FIBER_OBJECT_H
|
||||
#define BOOST_FIBERS_DETAIL_ASYM_FIBER_OBJECT_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/asym_fiber_base.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
template< typename Fn >
|
||||
class asym_fiber_object : public asym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn fn_;
|
||||
|
||||
asym_fiber_object( asym_fiber_object &);
|
||||
asym_fiber_object & operator=( asym_fiber_object const&);
|
||||
|
||||
public:
|
||||
asym_fiber_object( Fn fn, std::size_t stacksize, do_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
asym_fiber_object( Fn fn, std::size_t stacksize, do_not_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class asym_fiber_object< BOOST_RV_REF( Fn) > : public asym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn fn_;
|
||||
|
||||
asym_fiber_object( asym_fiber_object &);
|
||||
asym_fiber_object & operator=( asym_fiber_object const&);
|
||||
|
||||
public:
|
||||
asym_fiber_object( BOOST_RV_REF( Fn) fn, std::size_t stacksize, do_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
asym_fiber_object( BOOST_RV_REF( Fn) fn, std::size_t stacksize, do_not_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class asym_fiber_object< reference_wrapper< Fn > > : public asym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn & fn_;
|
||||
|
||||
asym_fiber_object( asym_fiber_object &);
|
||||
asym_fiber_object & operator=( asym_fiber_object const&);
|
||||
|
||||
public:
|
||||
asym_fiber_object( reference_wrapper< Fn > fn, std::size_t stacksize, do_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
asym_fiber_object( reference_wrapper< Fn > fn, std::size_t stacksize, do_not_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class asym_fiber_object< const reference_wrapper< Fn > > : public asym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn & fn_;
|
||||
|
||||
asym_fiber_object( asym_fiber_object &);
|
||||
asym_fiber_object & operator=( asym_fiber_object const&);
|
||||
|
||||
public:
|
||||
asym_fiber_object( const reference_wrapper< Fn > fn, std::size_t stacksize, do_return_t v) :
|
||||
asym_fiber_base( stacksize, v),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_ASYM_FIBER_OBJECT_H
|
||||
@@ -1,33 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
// this file is based on config.hpp of boost.thread
|
||||
|
||||
#ifndef BOOST_FIBERS_DETAIL_CONFIG_H
|
||||
#define BOOST_FIBERS_DETAIL_CONFIG_H
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
#if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FIBER_DYN_LINK)
|
||||
# if defined(BOOST_FIBER_SOURCE)
|
||||
# define BOOST_FIBER_DECL BOOST_SYMBOL_EXPORT
|
||||
# else
|
||||
# define BOOST_FIBER_DECL BOOST_SYMBOL_IMPORT
|
||||
# endif
|
||||
#else
|
||||
# define BOOST_FIBER_DECL
|
||||
#endif
|
||||
|
||||
#if ! defined(BOOST_FIBER_SOURCE) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_FIBER_NO_LIB)
|
||||
# define BOOST_LIB_NAME boost_fiber
|
||||
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FIBER_DYN_LINK)
|
||||
# define BOOST_DYN_LINK
|
||||
# endif
|
||||
# include <boost/config/auto_link.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_CONFIG_H
|
||||
@@ -1,84 +0,0 @@
|
||||
|
||||
// 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_SYM_FIBER_BASE_H
|
||||
#define BOOST_FIBERS_DETAIL_SYM_FIBER_BASE_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <stack>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/all.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4251)
|
||||
#pragma warning(disable:4275)
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
namespace detail {
|
||||
|
||||
BOOST_FIBER_DECL void trampoline_sym( void *);
|
||||
|
||||
class BOOST_FIBER_DECL sym_fiber_base : private noncopyable
|
||||
{
|
||||
public:
|
||||
typedef intrusive_ptr< sym_fiber_base > ptr;
|
||||
|
||||
friend BOOST_FIBER_DECL void trampoline_sym( void * vp);
|
||||
|
||||
friend inline void intrusive_ptr_add_ref( sym_fiber_base * p)
|
||||
{ ++p->use_count_; }
|
||||
|
||||
friend inline void intrusive_ptr_release( sym_fiber_base * p)
|
||||
{ if ( --p->use_count_ == 0) delete p; }
|
||||
|
||||
sym_fiber_base();
|
||||
|
||||
sym_fiber_base( std::size_t stacksize);
|
||||
|
||||
sym_fiber_base( std::size_t stacksize, sym_fiber_base & nxt);
|
||||
|
||||
virtual ~sym_fiber_base() {}
|
||||
|
||||
void switch_to( sym_fiber_base & other);
|
||||
|
||||
void set_finished();
|
||||
|
||||
bool get_finished() const;
|
||||
|
||||
protected:
|
||||
virtual void exec() = 0;
|
||||
|
||||
private:
|
||||
unsigned int use_count_;
|
||||
bool finished_;
|
||||
context<> ctx_;
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_SYM_FIBER_BASE_H
|
||||
@@ -1,145 +0,0 @@
|
||||
|
||||
// Copyright Oliver Kowalke 2009.
|
||||
// Distributed under the Boost Software Licenseersion 1.0.
|
||||
// (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#ifndef BOOST_FIBERS_DETAIL_SYM_FIBER_OBJECT_H
|
||||
#define BOOST_FIBERS_DETAIL_SYM_FIBER_OBJECT_H
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/sym_fiber_base.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
class sym_fiber_dummy : public sym_fiber_base
|
||||
{
|
||||
private:
|
||||
sym_fiber_dummy( sym_fiber_dummy &);
|
||||
sym_fiber_dummy & operator=( sym_fiber_dummy const&);
|
||||
|
||||
public:
|
||||
sym_fiber_dummy() :
|
||||
sym_fiber_base()
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ BOOST_ASSERT( false && "should not be invoked"); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class sym_fiber_object : public sym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn fn_;
|
||||
|
||||
sym_fiber_object( sym_fiber_object &);
|
||||
sym_fiber_object & operator=( sym_fiber_object const&);
|
||||
|
||||
public:
|
||||
sym_fiber_object( Fn fn, std::size_t stacksize) :
|
||||
sym_fiber_base( stacksize),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
sym_fiber_object( Fn fn, std::size_t stacksize, sym_fiber_base & nxt) :
|
||||
sym_fiber_base( stacksize, nxt),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class sym_fiber_object< BOOST_RV_REF( Fn) > : public sym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn fn_;
|
||||
|
||||
sym_fiber_object( sym_fiber_object &);
|
||||
sym_fiber_object & operator=( sym_fiber_object const&);
|
||||
|
||||
public:
|
||||
sym_fiber_object( BOOST_RV_REF( Fn) fn, std::size_t stacksize) :
|
||||
sym_fiber_base( stacksize),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
sym_fiber_object( BOOST_RV_REF( Fn) fn, std::size_t stacksize, sym_fiber_base & nxt) :
|
||||
sym_fiber_base( stacksize, nxt),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class sym_fiber_object< reference_wrapper< Fn > > : public sym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn & fn_;
|
||||
|
||||
sym_fiber_object( sym_fiber_object &);
|
||||
sym_fiber_object & operator=( sym_fiber_object const&);
|
||||
|
||||
public:
|
||||
sym_fiber_object( reference_wrapper< Fn > fn, std::size_t stacksize) :
|
||||
sym_fiber_base( stacksize),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
sym_fiber_object( reference_wrapper< Fn > fn, std::size_t stacksize, sym_fiber_base & nxt) :
|
||||
sym_fiber_base( stacksize, nxt),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
template< typename Fn >
|
||||
class sym_fiber_object< const reference_wrapper< Fn > > : public sym_fiber_base
|
||||
{
|
||||
private:
|
||||
Fn & fn_;
|
||||
|
||||
sym_fiber_object( sym_fiber_object &);
|
||||
sym_fiber_object & operator=( sym_fiber_object const&);
|
||||
|
||||
public:
|
||||
sym_fiber_object( const reference_wrapper< Fn > fn, std::size_t stacksize) :
|
||||
sym_fiber_base( stacksize),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
sym_fiber_object( const reference_wrapper< Fn > fn, std::size_t stacksize, sym_fiber_base & nxt) :
|
||||
sym_fiber_base( stacksize, nxt),
|
||||
fn_( fn)
|
||||
{}
|
||||
|
||||
void exec()
|
||||
{ fn_(); }
|
||||
};
|
||||
|
||||
}}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_DETAIL_SYM_FIBER_OBJECT_H
|
||||
@@ -1,38 +0,0 @@
|
||||
|
||||
// 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_EXCEPTIONS_H
|
||||
#define BOOST_FIBERS_EXCEPTIONS_H
|
||||
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
class BOOST_FIBER_DECL fiber_moved : public std::logic_error
|
||||
{
|
||||
public:
|
||||
fiber_moved() :
|
||||
std::logic_error("fiber moved")
|
||||
{}
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_EXCEPTIONS_H
|
||||
@@ -1,276 +0,0 @@
|
||||
|
||||
// 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_SYM_FIBER_H
|
||||
#define BOOST_FIBERS_SYM_FIBER_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <boost/preprocessor/repetition.hpp>
|
||||
#include <boost/move/move.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/detail/config.hpp>
|
||||
#include <boost/fiber/detail/sym_fiber_base.hpp>
|
||||
#include <boost/fiber/detail/sym_fiber_object.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4251)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
class BOOST_FIBER_DECL sym_fiber
|
||||
{
|
||||
private:
|
||||
struct dummy {};
|
||||
|
||||
BOOST_COPYABLE_AND_MOVABLE( sym_fiber);
|
||||
|
||||
detail::sym_fiber_base::ptr impl_;
|
||||
|
||||
sym_fiber( detail::sym_fiber_base::ptr const& impl);
|
||||
|
||||
static detail::sym_fiber_base::ptr make_fiber_(
|
||||
void( * fn)(), std::size_t stacksize)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< void(*)() >( fn, stacksize) );
|
||||
}
|
||||
|
||||
static detail::sym_fiber_base::ptr make_fiber_( void( * fn)(),
|
||||
std::size_t stacksize, detail::sym_fiber_base::ptr & nxt)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< void(*)() >( fn, stacksize, * nxt) );
|
||||
}
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber_(
|
||||
Fn & fn, std::size_t stacksize)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber_(
|
||||
Fn & fn, std::size_t stacksize, detail::sym_fiber_base::ptr & nxt)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize, * nxt) );
|
||||
}
|
||||
#else
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber_(
|
||||
Fn fn, std::size_t stacksize)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber_(
|
||||
Fn fn, std::size_t stacksize, detail::sym_fiber_base::ptr & nxt)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize, * nxt) );
|
||||
}
|
||||
#endif
|
||||
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber__(
|
||||
BOOST_RV_REF( Fn) fn, std::size_t stacksize)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize) );
|
||||
}
|
||||
|
||||
template< typename Fn >
|
||||
static detail::sym_fiber_base::ptr make_fiber__( BOOST_RV_REF( Fn) fn,
|
||||
std::size_t stacksize, detail::sym_fiber_base::ptr & nxt)
|
||||
{
|
||||
return detail::sym_fiber_base::ptr(
|
||||
new detail::sym_fiber_object< Fn >( fn, stacksize, * nxt) );
|
||||
}
|
||||
|
||||
public:
|
||||
static std::size_t max_stacksize;
|
||||
static std::size_t min_stacksize;
|
||||
static std::size_t default_stacksize;
|
||||
|
||||
static sym_fiber from_current_context();
|
||||
|
||||
class id;
|
||||
|
||||
sym_fiber();
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
template< typename Fn >
|
||||
sym_fiber( Fn & fn, std::size_t stacksize) :
|
||||
impl_( make_fiber_( fn, stacksize) )
|
||||
{}
|
||||
|
||||
template< typename Fn >
|
||||
sym_fiber( Fn & fn, std::size_t stacksize, sym_fiber & nxt) :
|
||||
impl_( make_fiber_( fn, stacksize, nxt.impl_) )
|
||||
{}
|
||||
#else
|
||||
template< typename Fn >
|
||||
sym_fiber( Fn fn, std::size_t stacksize) :
|
||||
impl_( make_fiber_( fn, stacksize) )
|
||||
{}
|
||||
|
||||
template< typename Fn >
|
||||
sym_fiber( Fn fn, std::size_t stacksize, sym_fiber & nxt) :
|
||||
impl_( make_fiber_( fn, stacksize, nxt.impl_) )
|
||||
{}
|
||||
#endif
|
||||
|
||||
template< typename Fn >
|
||||
sym_fiber( BOOST_RV_REF( Fn) fn, std::size_t stacksize) :
|
||||
impl_( make_fiber__( fn, stacksize) )
|
||||
{}
|
||||
|
||||
template< typename Fn >
|
||||
sym_fiber( BOOST_RV_REF( Fn) fn, std::size_t stacksize, sym_fiber & nxt) :
|
||||
impl_( make_fiber__( fn, stacksize, nxt.impl_) )
|
||||
{}
|
||||
|
||||
#define BOOST_FIBERS_SYM_FIBER_ARG(z, n, unused) \
|
||||
BOOST_PP_CAT(A, n) BOOST_PP_CAT(a, n)
|
||||
#define BOOST_ENUM_FIBERS_SYM_FIBER_ARGS(n) BOOST_PP_ENUM(n, BOOST_FIBERS_SYM_FIBER_ARG, ~)
|
||||
|
||||
#define BOOST_FIBERS_SYM_FIBER_CTOR(z, n, unused) \
|
||||
template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
||||
sym_fiber( Fn fn, BOOST_ENUM_FIBERS_SYM_FIBER_ARGS(n), std::size_t stacksize) : \
|
||||
impl_( \
|
||||
make_fiber_( \
|
||||
boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
|
||||
stacksize) ) \
|
||||
{} \
|
||||
\
|
||||
template< typename Fn, BOOST_PP_ENUM_PARAMS(n, typename A) > \
|
||||
sym_fiber( Fn fn, BOOST_ENUM_FIBERS_SYM_FIBER_ARGS(n), std::size_t stacksize, sym_fiber & nxt) : \
|
||||
impl_( \
|
||||
make_fiber_( \
|
||||
boost::bind( boost::type< void >(), fn, BOOST_PP_ENUM_PARAMS(n, a) ), \
|
||||
stacksize, nxt.impl_) ) \
|
||||
{} \
|
||||
|
||||
#ifndef BOOST_FIBERS_SYM_MAX_ARITY
|
||||
#define BOOST_FIBERS_SYM_MAX_ARITY 10
|
||||
#endif
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_FIBERS_SYM_MAX_ARITY, BOOST_FIBERS_SYM_FIBER_CTOR, ~)
|
||||
|
||||
#undef BOOST_FIBERS_SYM_MAY_ARITY
|
||||
#undef BOOST_FIBERS_SYM_FIBER_ARG
|
||||
#undef BOOST_FIBERS_SYM_FIBER_ARGS
|
||||
#undef BOOST_FIBERS_SYM_FIBER_CTOR
|
||||
|
||||
sym_fiber( sym_fiber const& other);
|
||||
|
||||
sym_fiber & operator=( BOOST_COPY_ASSIGN_REF( sym_fiber) other);
|
||||
|
||||
sym_fiber( BOOST_RV_REF( sym_fiber) other);
|
||||
|
||||
sym_fiber & operator=( BOOST_RV_REF( sym_fiber) other);
|
||||
|
||||
typedef detail::sym_fiber_base::ptr::unspecified_bool_type unspecified_bool_type;
|
||||
|
||||
operator unspecified_bool_type() const;
|
||||
|
||||
bool operator!() const;
|
||||
|
||||
void swap( sym_fiber & other);
|
||||
|
||||
id get_id() const;
|
||||
|
||||
bool operator==( sym_fiber const& other) const;
|
||||
bool operator!=( sym_fiber const& other) const;
|
||||
|
||||
void switch_to( sym_fiber & other);
|
||||
|
||||
bool finished() const;
|
||||
};
|
||||
|
||||
class BOOST_FIBER_DECL sym_fiber::id
|
||||
{
|
||||
private:
|
||||
friend class sym_fiber;
|
||||
|
||||
boost::uint64_t id_;
|
||||
|
||||
explicit id( detail::sym_fiber_base::ptr const& info) :
|
||||
id_( reinterpret_cast< boost::uint64_t >( info.get() ) )
|
||||
{}
|
||||
|
||||
public:
|
||||
id() :
|
||||
id_( 0)
|
||||
{}
|
||||
|
||||
bool operator==( id const& other) const
|
||||
{ return id_ == other.id_; }
|
||||
|
||||
bool operator!=( id const& other) const
|
||||
{ return id_ != other.id_; }
|
||||
|
||||
bool operator<( id const& other) const
|
||||
{ return id_ < other.id_; }
|
||||
|
||||
bool operator>( id const& other) const
|
||||
{ return other.id_ < id_; }
|
||||
|
||||
bool operator<=( id const& other) const
|
||||
{ return !( other.id_ < id_); }
|
||||
|
||||
bool operator>=( id const& other) const
|
||||
{ return ! ( id_ < other.id_); }
|
||||
|
||||
template< typename charT, class traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream< charT, traitsT > & os, id const& other)
|
||||
{
|
||||
if ( 0 != other.id_) return os << other.id_;
|
||||
else return os << "{not-a-fiber}";
|
||||
}
|
||||
};
|
||||
|
||||
inline
|
||||
void swap( sym_fiber & l, sym_fiber & r)
|
||||
{ return l.swap( r); }
|
||||
|
||||
}
|
||||
|
||||
using fibers::sym_fiber;
|
||||
|
||||
}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
|
||||
#endif // BOOST_FIBERS_SYM_FIBER_H
|
||||
@@ -1,31 +0,0 @@
|
||||
# Boost.fiber Library Build Jamfile
|
||||
|
||||
# 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)
|
||||
|
||||
import feature ;
|
||||
import modules ;
|
||||
import toolset ;
|
||||
|
||||
project boost/fiber
|
||||
: source-location ../src
|
||||
: requirements
|
||||
<dependency>../../context/build//context.hpp
|
||||
: usage-requirements
|
||||
<link>shared:<define>BOOST_FIBER_DYN_LINK=1
|
||||
;
|
||||
|
||||
lib boost_fiber
|
||||
: asym_fiber.cpp
|
||||
sym_fiber.cpp
|
||||
detail/asym_fiber_base.cpp
|
||||
detail/sym_fiber_base.cpp
|
||||
../../context/build//boost_context
|
||||
: <link>shared:<define>BOOST_FIBER_DYN_LINK=1
|
||||
:
|
||||
: <link>shared:<library>../../context/build//boost_context
|
||||
;
|
||||
|
||||
boost-install boost_fiber ;
|
||||
@@ -1,33 +0,0 @@
|
||||
# (C) Copyright 2008 Anthony Williams
|
||||
#
|
||||
# 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)
|
||||
|
||||
path-constant boost-images : ../../../doc/src/images ;
|
||||
|
||||
xml fiber : fiber.qbk ;
|
||||
|
||||
boostbook standalone
|
||||
:
|
||||
fiber
|
||||
:
|
||||
# HTML options first:
|
||||
# Use graphics not text for navigation:
|
||||
<xsl:param>navig.graphics=1
|
||||
# How far down we chunk nested sections, basically all of them:
|
||||
<xsl:param>chunk.section.depth=3
|
||||
# Don't put the first section on the same page as the TOC:
|
||||
<xsl:param>chunk.first.sections=1
|
||||
# How far down sections get TOC's
|
||||
<xsl:param>toc.section.depth=10
|
||||
# Max depth in each TOC:
|
||||
<xsl:param>toc.max.depth=3
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=10
|
||||
# Path for links to Boost:
|
||||
<xsl:param>boost.root=../../../..
|
||||
# Path for libraries index:
|
||||
<xsl:param>boost.libraries=../../../../libs/libraries.htm
|
||||
# Use the main Boost stylesheet:
|
||||
<xsl:param>html.stylesheet=../../../../doc/html/boostbook.css
|
||||
;
|
||||
@@ -1,425 +0,0 @@
|
||||
[/
|
||||
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
|
||||
]
|
||||
|
||||
[section:asym_fiber_management Asymmetric Fiber]
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
Each __asym_fiber__ class represents a user-space context of execution. Objects of
|
||||
type __asym_fiber__ are characterized by providing three basic operations: __create__
|
||||
(constructor), __resume__ (__fiber_run__) and __suspend__ (__fiber_yield__).
|
||||
|
||||
The constructor of __asym_fiber__ accepts a function which acts as the main body
|
||||
of the fiber. Creating a fiber doesn't start its execution. The fiber begins
|
||||
in suspended state with its __continuation_point__ set to the first instruction in
|
||||
its main body.
|
||||
Invoking __fiber_run__ starts the execution at its saved __continuation_point__
|
||||
(activate the fiber) and runs until the fiber gets suspended or returns from fibers
|
||||
main function. In both cases the control is transfered back to the invoker.
|
||||
When a fiber returns from its main function the fiber is said to be finished and can
|
||||
not be futher resumed.
|
||||
If a fiber gets suspended its __continuation_point__ is saved so that the next time
|
||||
the fiber is resumed, its execution will continue at the exact point where it was
|
||||
suspended.
|
||||
|
||||
__asym_fiber__ supports copy- and move-semantics.
|
||||
|
||||
boost::asym_fiber f1; // not-a-fiber
|
||||
|
||||
void fn()
|
||||
{
|
||||
boost::asym_fiber f2( some_fn, boost::asym_fiber::default_stacksize);
|
||||
std::cout << f2.get_id() << std::endl;
|
||||
f2.run();
|
||||
}
|
||||
|
||||
|
||||
[note If fibers are migrated between threads the code called by a fiber must not
|
||||
use thread-local-storage.]
|
||||
|
||||
|
||||
[heading Creating]
|
||||
|
||||
A new fiber is launched by passing an object of a callable type that can be
|
||||
invoked with no parameters to the constructor. The object is then copied into
|
||||
internal storage, and invoked on the newly-created fiber. If the object must
|
||||
not (or cannot) be copied, then `boost::ref` can be used to pass in a reference
|
||||
to the function object. In this case, the user of __boost_fiber__ must ensure
|
||||
that the referred-to object outlives the newly-created fiber.
|
||||
|
||||
struct callable
|
||||
{ void operator()(); };
|
||||
|
||||
boost::asym_fiber copies_are_safe()
|
||||
{
|
||||
callable x;
|
||||
return boost::asym_fiber( x);
|
||||
} // x is destroyed, but the newly-created fiber has a copy, so this is OK
|
||||
|
||||
boost::asym_fiber oops()
|
||||
{
|
||||
callable x;
|
||||
return boost::asym_fiber( boost::ref( x), boost::asym_fiber::default_stacksize);
|
||||
} // x is destroyed, but the newly-created fiber still has a reference
|
||||
// this leads to undefined behaviour
|
||||
|
||||
If you wish to construct an instance of __asym_fiber__ with a function or callable
|
||||
object that requires arguments to be supplied, this can be done by passing
|
||||
additional arguments to the __asym_fiber__ constructor:
|
||||
|
||||
void find_the_question( int the_answer);
|
||||
|
||||
boost::asym_fiber deep_thought_2(
|
||||
find_the_question, 42, boost::asym_fiber::default_stacksize);
|
||||
|
||||
The arguments are ['copied] into the internal fiber structure: if a reference
|
||||
is required, use `boost::ref`, just as for references to callable functions.
|
||||
|
||||
[caution Functions passed to the __asym_fiber__ must not throw exceptions.]
|
||||
|
||||
If the main function of __asym_fiber__ returns the fiber returns to the
|
||||
__continuation_point__ which has invoked the fiber. If desired the application
|
||||
will terminate if the last constructor argument is set to `false` and fibers
|
||||
main function returns.
|
||||
|
||||
|
||||
[heading Control Transfer]
|
||||
|
||||
__asym_fiber__ has two operations to transfer the execution between different
|
||||
fibers. The __continuation_point__ of the fiber ist started/resumed if
|
||||
__fiber_run__ is invoked.
|
||||
If the fiber decides to give the execution control back to its caller
|
||||
__fiber_yield__ must be called.
|
||||
|
||||
// create `my_fiber` which will execute `my_function()`
|
||||
boost::asym_fiber my_fiber( my_function, boost::asym_fiber:default_stacksize);
|
||||
|
||||
// jump to execution context of `my_fiber`
|
||||
// run `my_function`
|
||||
my_fiber.run();
|
||||
|
||||
// this section will be entered if `my_function()` calls
|
||||
// `my_fiber.yield()`
|
||||
|
||||
|
||||
[heading Fiber IDs]
|
||||
|
||||
Objects of class __asym_fiber_id__ can be used to identify fibers. Each running fiber
|
||||
has a unique ID obtainable from the corresponding __asym_fiber__ by calling
|
||||
__asym_get_id__ member function. Objects of class __asym_fiber_id__ can be copied, and
|
||||
used as keys in associative containers: the full range of comparison operators
|
||||
is provided. Fiber IDs can also be written to an output stream using the stream
|
||||
insertion operator, though the output format is unspecified.
|
||||
|
||||
Each instance of __asym_fiber_id__ either refers to some fiber, or __not_a_fiber__.
|
||||
Instances that refer to __not_a_fiber__ compare equal to each other, but not
|
||||
equal to any instances that refer to an actual fiber.
|
||||
The comparison operators on __asym_fiber_id__ yield a total order for every non-equal
|
||||
fiber ID.
|
||||
|
||||
|
||||
[heading Example]
|
||||
|
||||
The example below demonstrates that the function `fn` is executed in the context
|
||||
of the fiber `f` and the local state of `fn` is preserved (value of `i` in the
|
||||
for loop).
|
||||
|
||||
boost::asym_fiber f;
|
||||
|
||||
void fn( int n)
|
||||
{
|
||||
for ( int i = 0; i < n; ++i)
|
||||
{
|
||||
std::cout << i << " iteration" << std::endl;
|
||||
// jump back to main
|
||||
// value of i will be preserved
|
||||
f.yield();
|
||||
// if we return from f.yield()
|
||||
// f.run() was called again
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
f = boost::asym_fiber( fn, 5);
|
||||
|
||||
std::cout << "start" << std::endl;
|
||||
while ( ! f.finished() )
|
||||
f.run(); // jump to context of fn()
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
[section:asym_fiber Class `asym_fiber`]
|
||||
|
||||
#include <boost/fiber/asym_fiber.hpp>
|
||||
|
||||
class asym_fiber
|
||||
{
|
||||
public:
|
||||
static std::size_t max_stacksize;
|
||||
static std::size_t min_stacksize;
|
||||
static std::size_t default_stacksize; // 256 kB
|
||||
|
||||
asym_fiber();
|
||||
|
||||
template< typename Fn >
|
||||
explicit asym_fiber( Fn fn, std::size_t stacksize, bool do_return = true);
|
||||
|
||||
template< typename Fn, typename A1, typename A2,... >
|
||||
asym_fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize, bool do_return = true);
|
||||
|
||||
asym_fiber( asym_fiber const& other);
|
||||
asym_fiber & operator=( asym_fiber const& other);
|
||||
|
||||
// move support
|
||||
template< typename Fn >
|
||||
explicit asym_fiber( Fn && fn, std::size_t stacksize, bool do_return = true);
|
||||
|
||||
asym_fiber( asym_fiber && other);
|
||||
|
||||
asym_fiber & operator=( asym_fiber && other);
|
||||
|
||||
operator unspecified-bool-type() const;
|
||||
|
||||
bool operator!() const;
|
||||
|
||||
void swap( asym_fiber & other);
|
||||
|
||||
id get_id() const;
|
||||
|
||||
bool operator==( asym_fiber const&) const;
|
||||
bool operator!=( asym_fiber const&) const;
|
||||
|
||||
void run();
|
||||
|
||||
void yield();
|
||||
|
||||
bool finished() const;
|
||||
};
|
||||
|
||||
void swap( asym_fiber & lhs, asym_fiber & rhs);
|
||||
|
||||
|
||||
[section:default_constructor `asym_fiber()`]
|
||||
[variablelist
|
||||
[[Effects:] [Constructs a __asym_fiber__ instance that refers to __not_a_fiber__.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:callable_constructor_stack `template< typename Fn > asym_fiber( Fn fn, std::size_t stacksize, bool do_return)`]
|
||||
[variablelist
|
||||
[[Effects:] [`fn` is copied into storage managed internally by the fiber, that
|
||||
copy is invoked on a newly-created fiber. If last argument is
|
||||
`true` the execution context returns to caller after `fn` finished.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:multiple_argument_constructor `template< typename Fn, typename A1, typename A2,... > fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize, bool do_return)`]
|
||||
[variablelist
|
||||
[[Preconditions:] [`Fn` and each `A`n must by copyable or movable.]]
|
||||
[[Effects:] [As if `asym_fiber( boost::bind( fn, a1, a2,...) )`. Consequently,
|
||||
`fn` and each `a`n are copied into internal storage for access by the new fiber.
|
||||
If last argument is `true` the execution context returns to caller after `fn`
|
||||
finished.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__]]
|
||||
[[Note:] [Currently up to nine additional arguments `a1` to `a9` can be
|
||||
specified in addition to the function `fn`.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:get_id `asym_fiber::id get_id() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers to a fiber, an instance of __asym_fiber_id__ that
|
||||
represents that fiber. Otherwise returns a default-constructed __asym_fiber_id__.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:run `void run()`]
|
||||
[variablelist
|
||||
[[Effects:] [Save current execution context (caller) and jump to execution
|
||||
context of `*this`.]]
|
||||
[[Throws:] [__fiber_moved__ if `*this` is __not_a_fiber__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:yield `void yield()`]
|
||||
[variablelist
|
||||
[[Effects:] [Save execution context of `*this` and jump back to callers
|
||||
execution context.]]
|
||||
[[Throws:] [__fiber_moved__ if `*this` is __not_a_fiber__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:finished `bool finished() const`]
|
||||
[variablelist
|
||||
[[Effects:] [Returns `true` if fiber has finished.]]
|
||||
[[Throws:] [__fiber_moved__ if `*this` is __not_a_fiber__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:unspec_operator `operator unspecified-bool-type() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers to a fiber, the function returns true. Otherwise
|
||||
false.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_operator `bool operator!() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers not to a fiber, the function returns true.
|
||||
Otherwise false.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:equals `bool operator==( asym_fiber const& other) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`get_id()==other.get_id()`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_equals `bool operator!=( asym_fiber const& other) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`get_id()!=other.get_id()`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:swap `void swap( asym_fiber & other)`]
|
||||
[variablelist
|
||||
[[Effects:] [Exchanges the fibers associated with `*this` and `other`, so
|
||||
`*this` is associated with the fiber associated with `other` prior to the call,
|
||||
and vice-versa.]]
|
||||
[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()`
|
||||
prior to the call. `other.get_id()` returns the same value as `this->get_id()`
|
||||
prior to the call.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:non_member_swap Non-member function `swap()`]
|
||||
|
||||
#include <boost/fiber/asym_fiber.hpp>
|
||||
|
||||
void swap( asym_fiber & lhs, asym_fiber & rhs);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [[link fiber.asym_fiber_management.asym_fiber.swap
|
||||
`lhs.swap( rhs)`].]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:id Class `boost::asym_fiber::id`]
|
||||
|
||||
#include <boost/fiber/fiber.hpp>
|
||||
|
||||
class asym_fiber::id
|
||||
{
|
||||
public:
|
||||
id();
|
||||
|
||||
bool operator==( id const& y) const;
|
||||
bool operator!=( id const& y) const;
|
||||
bool operator<( id const& y) const;
|
||||
bool operator>( id const& y) const;
|
||||
bool operator<=( id const& y) const;
|
||||
bool operator>=( id const& y) const;
|
||||
|
||||
template< typename charT, typename traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream<charT, traitsT > & os, id const& x);
|
||||
};
|
||||
|
||||
[section:constructor `id()`]
|
||||
[variablelist
|
||||
[[Effects:] [Constructs a __asym_fiber_id__ instance that represents
|
||||
__not_a_fiber__.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:is_equal `bool operator==( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `y` both represent the same fiber of
|
||||
execution, or both represent __not_a_fiber__, `false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_equal `bool operator!=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `y` represent different fibers of execution,
|
||||
or one represents a fiber of execution, and the other represent __not_a_fiber__,
|
||||
`false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:less_than `bool operator<( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this!=y` is `true` and the implementation-defined total
|
||||
order of __asym_fiber_id__ values places `*this` before `y`, `false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
[[Note:] [A __asym_fiber_id__ instance representing __not_a_fiber__ will always
|
||||
compare less than an instance representing a fiber of
|
||||
execution.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:greater_than `bool operator>( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`y<*this`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:less_than_or_equal `bool operator<=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`!(y<*this)`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:greater_than_or_equal `bool operator>=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`!(*this<y)`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:stream_out Non-member template function `operator<<`]
|
||||
|
||||
template< typename charT, typename traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream<charT, traitsT > & os, id const& x);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Writes a representation of the __asym_fiber_id__ instance `x` to
|
||||
the stream `os`, such that the representation of two instances of
|
||||
__asym_fiber_id__ `a` and `b` is the same if `a==b`, and different if `a!=b`.]]
|
||||
[[Returns:] [`os`]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
@@ -1,53 +0,0 @@
|
||||
[/
|
||||
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
|
||||
]
|
||||
|
||||
[article Fiber
|
||||
[quickbook 1.4]
|
||||
[authors [Kowalke, Oliver]]
|
||||
[copyright 2009 Oliver Kowalke]
|
||||
[purpose C++ Library providing an symmetric and asymmetric continuation framework]
|
||||
[category text]
|
||||
[license
|
||||
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])
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
[def __boost_context__ [*Boost.Context]]
|
||||
[def __boost_fiber__ [*Boost.Fiber]]
|
||||
[def __boost_move__ [*Boost.Move]]
|
||||
|
||||
[def __blocked__ ['blocked]]
|
||||
[def __continuation_point__ ['continuation point]]
|
||||
[def __fiber_id__ ['fiber-id]]
|
||||
[def __not_a_fiber__ ['not-a-fiber]]
|
||||
[def __create__ ['create]]
|
||||
[def __resume__ ['resume]]
|
||||
[def __suspend__ ['suspend]]
|
||||
[def __yield__ ['yield]]
|
||||
|
||||
[def __asym_get_id__ `boost::asym_fiber::get_id()`]
|
||||
[def __fiber_run__ `boost::asym_fiber::run()`]
|
||||
[def __fiber_switch_to__ `boost::sym_fiber::switch_to()`]
|
||||
[def __fiber_yield__ `boost::asym_fiber::yield()`]
|
||||
[def __sym_get_id__ `boost::sym_fiber::get_id()`]
|
||||
|
||||
[def __asym_fiber__ `boost::asym_fiber`]
|
||||
[def __asym_fiber_id__ `boost::asym_fiber::id`]
|
||||
[def __bad_alloc__ `std::bad_alloc`]
|
||||
[def __fcontext__ `fcontext_t`]
|
||||
[def __fiber_moved__ `boost::fibers::fiber_moved`]
|
||||
[def __sym_fiber__ `boost::sym_fiber`]
|
||||
[def __sym_fiber_id__ `boost::sym_fiber::id`]
|
||||
[def __ucontext__ `ucontext_t`]
|
||||
|
||||
|
||||
[include overview.qbk]
|
||||
[include asym_fiber_ref.qbk]
|
||||
[include sym_fiber_ref.qbk]
|
||||
@@ -1,36 +0,0 @@
|
||||
index.html
|
||||
fiber/overview.html
|
||||
fiber/asym_fiber_management.html
|
||||
fiber/asym_fiber_management/asym_fiber.html
|
||||
fiber/asym_fiber_management/asym_fiber/default_constructor.html
|
||||
fiber/asym_fiber_management/asym_fiber/callable_constructor_stack.html
|
||||
fiber/asym_fiber_management/asym_fiber/multiple_argument_constructor.html
|
||||
fiber/asym_fiber_management/asym_fiber/get_id.html
|
||||
fiber/asym_fiber_management/asym_fiber/run.html
|
||||
fiber/asym_fiber_management/asym_fiber/yield.html
|
||||
fiber/asym_fiber_management/asym_fiber/finished.html
|
||||
fiber/asym_fiber_management/asym_fiber/unspec_operator.html
|
||||
fiber/asym_fiber_management/asym_fiber/not_operator.html
|
||||
fiber/asym_fiber_management/asym_fiber/equals.html
|
||||
fiber/asym_fiber_management/asym_fiber/not_equals.html
|
||||
fiber/asym_fiber_management/asym_fiber/swap.html
|
||||
fiber/asym_fiber_management/asym_fiber/non_member_swap.html
|
||||
fiber/asym_fiber_management/asym_fiber/id.html
|
||||
fiber/sym_fiber_management.html
|
||||
fiber/sym_fiber_management/sym_fiber.html
|
||||
fiber/sym_fiber_management/sym_fiber/create.html
|
||||
fiber/sym_fiber_management/sym_fiber/default_constructor.html
|
||||
fiber/sym_fiber_management/sym_fiber/callable_constructor_stack1.html
|
||||
fiber/sym_fiber_management/sym_fiber/callable_constructor_stack2.html
|
||||
fiber/sym_fiber_management/sym_fiber/multiple_argument_constructor1.html
|
||||
fiber/sym_fiber_management/sym_fiber/multiple_argument_constructor2.html
|
||||
fiber/sym_fiber_management/sym_fiber/get_id.html
|
||||
fiber/sym_fiber_management/sym_fiber/switch_to.html
|
||||
fiber/sym_fiber_management/sym_fiber/finished.html
|
||||
fiber/sym_fiber_management/sym_fiber/unspec_operator.html
|
||||
fiber/sym_fiber_management/sym_fiber/not_operator.html
|
||||
fiber/sym_fiber_management/sym_fiber/equals.html
|
||||
fiber/sym_fiber_management/sym_fiber/not_equals.html
|
||||
fiber/sym_fiber_management/sym_fiber/swap.html
|
||||
fiber/sym_fiber_management/sym_fiber/non_member_swap.html
|
||||
fiber/sym_fiber_management/sym_fiber/id.html
|
||||
@@ -1,67 +0,0 @@
|
||||
[/
|
||||
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
|
||||
]
|
||||
|
||||
[section:overview Overview]
|
||||
|
||||
__boost_fiber__ provides an framework utilizing lightweight threads of execution
|
||||
- also known as user-space threads, microthreads or fibers. The API contains
|
||||
classes and functions to manage fibers.
|
||||
|
||||
A fiber is able to store the current execution state, including all registers
|
||||
and CPU flags, the instruction pointer, and the stack pointer and later restore
|
||||
this state (on behalf of __boost_context__). The idea is to have multiple
|
||||
execution paths running on a single thread using a sort of cooperative
|
||||
scheduling (threads are preemptively scheduled) - the running fiber decides
|
||||
explicitly when its yields to allow another fiber to run (fiber switching).
|
||||
Fibers are less expensive than threads because the kernel doesn't know anything
|
||||
about fibers - no kernel transitions are required for scheduling (done in the
|
||||
user-space).
|
||||
A context switch between threads costs usally thousends of CPU cycles on x86
|
||||
compared to a fiber switch with few hundreds of cycles.
|
||||
A fiber can only run on a single thread at any point in time but may be migrated
|
||||
between threads. Because a thread can run many different fibers during its life
|
||||
cycle the name ['fiber] was choosen.
|
||||
|
||||
Beside fibers a conceptualy equivalent constructs are coroutines. A coroutine
|
||||
can be seen as a language-level construct while a fiber is a system-level
|
||||
construct.
|
||||
|
||||
It is characteristic for a fiber that local data of a fiber persist between
|
||||
successive calls of the (symmetric or asymetric) control transfer operations.
|
||||
The __boost_fiber__ framework provides stackfull fiber implementations allowing
|
||||
to suspend and resume the execution from within nested functions.
|
||||
|
||||
[caution The documentation from __boost_context__ is relevant too.]
|
||||
|
||||
In order to use the classes and functions described here, you can either include
|
||||
the specific headers specified by the descriptions of each class or function, or
|
||||
include the master library header:
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
which includes all the other headers in turn.
|
||||
|
||||
Used namespaces is:
|
||||
|
||||
namespace boost::fibers
|
||||
|
||||
|
||||
[warning This library is ['not] an official Boost library]
|
||||
|
||||
__boost_fiber__ depends uppon __boost_context__ and
|
||||
__boost_move__.
|
||||
|
||||
|
||||
[heading How to build and install]
|
||||
|
||||
* download the sources from
|
||||
[@http://www.boost-consulting.com/vault/index.php?directory=Concurrent%20Programming Boost Vault]
|
||||
* extract the archive into the boost-source directory
|
||||
* call ['bjam] (take the different build options of __boost_context__ into acount)
|
||||
|
||||
|
||||
[endsect]
|
||||
@@ -1,475 +0,0 @@
|
||||
[/
|
||||
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
|
||||
]
|
||||
|
||||
[section:sym_fiber_management Symmetric Fiber]
|
||||
|
||||
[heading Synopsis]
|
||||
|
||||
Each __sym_fiber__ class represents a user-space context of execution. Objects of
|
||||
type __sym_fiber__ are characterized by providing two basic operations: __create__
|
||||
(constructor) and __suspend__ (__fiber_switch_to__).
|
||||
|
||||
The constructor of __sym_fiber__ accepts a function which acts as the main body
|
||||
of the fiber. Creating a fiber doesn't start its execution. The fiber begins
|
||||
in suspended state with its __continuation_point__ set to the first instruction in
|
||||
its main body.
|
||||
It is characeristic for symmetric fibers to provide a single control-transfer operation
|
||||
(__fiber_switch_to__) allowing to pass the control explicitly among themself.
|
||||
The __continuation_point__ of the fiber which initiates the control transfer will be
|
||||
saved so that the next time the cotnrol is transfered back its execution will continue
|
||||
at the exact point where it was suspended.
|
||||
When a fiber returns from its main function the fiber is said to be finished and can
|
||||
not be futher resumed. If a fibers main function returns and the fiber was not linked
|
||||
against another one, the application terminates.
|
||||
|
||||
__sym_fiber__ supports copy- and move-semantics.
|
||||
|
||||
boost::sym_fiber f1; // not-a-fiber
|
||||
|
||||
void fn()
|
||||
{
|
||||
boost::sym_fiber f2( some_fn, boost::sym_fiber::default_stacksize);
|
||||
std::cout << f2.get_id() << std::endl;
|
||||
f2.run();
|
||||
}
|
||||
|
||||
|
||||
[note If fibers are migrated between threads the code called by a fiber must not
|
||||
use thread-local-storage.]
|
||||
|
||||
|
||||
[heading Creating]
|
||||
|
||||
A new fiber is created by passing an object of a callable type that can be
|
||||
invoked with no parameters to the constructor. The object is then copied into
|
||||
internal storage, and invoked on the newly-created fiber. If the object must not
|
||||
(or cannot) be copied, then `boost::ref` can be used to pass in a reference to
|
||||
the function object. In this case, the user of __boost_fiber__ must ensure that
|
||||
the referred-to object outlives the newly-created fiber.
|
||||
|
||||
struct callable
|
||||
{ void operator()(); };
|
||||
|
||||
boost::sym_fiber copies_are_safe()
|
||||
{
|
||||
callable x;
|
||||
return boost::sym_fiber( x);
|
||||
} // x is destroyed, but the newly-created fiber has a copy, so this is OK
|
||||
|
||||
boost::sym_fiber oops()
|
||||
{
|
||||
callable x;
|
||||
return boost::sym_fiber( boost::ref( x), boost::sym_fiber::default_stacksize);
|
||||
} // x is destroyed, but the newly-created fiber still has a reference
|
||||
// this leads to undefined behaviour
|
||||
|
||||
If you wish to construct an instance of __sym_fiber__ with a function or callable
|
||||
object that requires arguments to be supplied, this can be done by passing
|
||||
additional arguments to the __sym_fiber__ constructor:
|
||||
|
||||
void find_the_question( int the_answer);
|
||||
|
||||
boost::sym_fiber deep_thought_2(
|
||||
find_the_question, 42, boost::sym_fiber::default_stacksize);
|
||||
|
||||
The arguments are ['copied] into the internal fiber structure: if a reference
|
||||
is required, use `boost::ref`, just as for references to callable functions.
|
||||
|
||||
[caution Functions passed to the __sym_fiber__ must not throw exceptions.]
|
||||
|
||||
|
||||
[heading Control Transfer]
|
||||
|
||||
__sym_fiber__ provides only one operation to transfer the execution control
|
||||
between different fibers. This allows the symmetric fibers to transfer the
|
||||
execution control among themselfs (chain of fiber invocations). The
|
||||
__continuation_point__ of the `other` fiber is started/resumed if
|
||||
__fiber_switch_to__ is called with `other` as its argument.
|
||||
|
||||
// create `current_fiber` which represent the current execution context
|
||||
boost::sym_fiber current_fiber( boost::sym_fiber::from_current-context() );
|
||||
|
||||
// create `my_fiber` which will execute `my_function()`
|
||||
boost::sym_fiber my_fiber( my_function, boost::sym_fiber:default_stacksize);
|
||||
|
||||
// jump to execution context of `my_fiber`
|
||||
// run `my_function`
|
||||
current_fiber.switch_to( my_fiber);
|
||||
|
||||
// this section will be entered if `my_function()` calls
|
||||
// `my_fiber.switch_to( current_fiber)`
|
||||
|
||||
|
||||
[heading Linking against other Fiber]
|
||||
|
||||
If the main function of a symmetric fiber returns the application terminates.
|
||||
If desired it is possible to link to another fiber which will be executed after
|
||||
a fiber is finished. For this purpose the constructor takes a __sym_fiber__ as
|
||||
last argument.
|
||||
|
||||
// create `current_fiber` which represent the current execution context
|
||||
boost::sym_fiber current_fiber( boost::sym_fiber::from_current-context() );
|
||||
|
||||
// create `my_fiber` which will execute `my_function()` and link
|
||||
// against `current_fiber` which will be resumed after `my_function()` returns
|
||||
boost::sym_fiber my_fiber( my_function, boost::sym_fiber:default_stacksize, current_fiber);
|
||||
|
||||
// jump to execution context of `my_fiber`
|
||||
// run `my_function`
|
||||
current_fiber.switch_to( my_fiber);
|
||||
|
||||
// this section will be entered if `my_function()` returns
|
||||
...
|
||||
|
||||
[heading Fiber IDs]
|
||||
|
||||
Objects of class __sym_fiber_id__ can be used to identify fibers. Each running fiber
|
||||
has a unique ID obtainable from the corresponding __sym_fiber__ by calling
|
||||
__sym_get_id__ member function. Objects of class __sym_fiber_id__ can be copied, and
|
||||
used as keys in associative containers: the full range of comparison operators
|
||||
is provided. Fiber IDs can also be written to an output stream using the stream
|
||||
insertion operator, though the output format is unspecified.
|
||||
|
||||
Each instance of __sym_fiber_id__ either refers to some fiber, or __not_a_fiber__.
|
||||
Instances that refer to __not_a_fiber__ compare equal to each other, but not
|
||||
equal to any instances that refer to an actual fiber.
|
||||
The comparison operators on __sym_fiber_id__ yield a total order for every non-equal
|
||||
fiber ID.
|
||||
|
||||
|
||||
[heading Example]
|
||||
|
||||
The example below demonstrates that the function `fn` is executed in the context
|
||||
of the fiber `f` and the local state of `fn` is preserved (value of `i` in the
|
||||
for loop).
|
||||
|
||||
boost::sym_fiber f, current;
|
||||
|
||||
void fn( int n)
|
||||
{
|
||||
for ( int i = 0; i < n; ++i)
|
||||
{
|
||||
std::cout << i << " iteration" << std::endl;
|
||||
// jump back to main
|
||||
// value of i will be preserved
|
||||
f.switch_to( current);
|
||||
// if we return from f.switch_to( current)
|
||||
// current.switch_to( f) was called again
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
current = boost::sym_fiber::from_current_context();
|
||||
f = boost::sym_fiber( fn, 5, current);
|
||||
|
||||
std::cout << "start" << std::endl;
|
||||
while ( ! f.finished() )
|
||||
current.switch_to( f); // jump to context of fn()
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
[section:sym_fiber Class `sym_fiber`]
|
||||
|
||||
#include <boost/fiber/sym_fiber.hpp>
|
||||
|
||||
class sym_fiber
|
||||
{
|
||||
public:
|
||||
static std::size_t max_stacksize;
|
||||
static std::size_t min_stacksize;
|
||||
static std::size_t default_stacksize; // 256 kB
|
||||
|
||||
static sym_fiber from_current_cotnext();
|
||||
|
||||
sym_fiber();
|
||||
|
||||
template< typename Fn >
|
||||
explicit sym_fiber( Fn fn, std::size_t stacksize);
|
||||
|
||||
template< typename Fn >
|
||||
explicit sym_fiber( Fn fn, std::size_t stacksize, sym_fiber & nxt);
|
||||
|
||||
template< typename Fn, typename A1, typename A2,... >
|
||||
sym_fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize);
|
||||
|
||||
template< typename Fn, typename A1, typename A2,... >
|
||||
sym_fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize, sym_fiber & nxt);
|
||||
|
||||
sym_fiber( sym_fiber const& other);
|
||||
sym_fiber & operator=( sym_fiber const& other);
|
||||
|
||||
// move support
|
||||
template< typename Fn >
|
||||
explicit sym_fiber( Fn && fn, std::size_t stacksize);
|
||||
|
||||
template< typename Fn >
|
||||
explicit sym_fiber( Fn && fn, std::size_t stacksize, sym_fiber & nxt);
|
||||
|
||||
sym_fiber( sym_fiber && other);
|
||||
|
||||
sym_fiber & operator=( sym_fiber && other);
|
||||
|
||||
operator unspecified-bool-type() const;
|
||||
|
||||
bool operator!() const;
|
||||
|
||||
void swap( sym_fiber & other);
|
||||
|
||||
id get_id() const;
|
||||
|
||||
bool operator==( sym_fiber const&) const;
|
||||
bool operator!=( sym_fiber const&) const;
|
||||
|
||||
void switch_to( sym_fiber & other);
|
||||
|
||||
bool finished() const;
|
||||
};
|
||||
|
||||
void swap( sym_fiber & lhs, sym_fiber & rhs);
|
||||
|
||||
|
||||
[section:create `static sym_fiber from_current_context()`]
|
||||
[variablelist
|
||||
[[Effects:] [Creates a fiber attached to current execution context.
|
||||
The fiber doesn't manage the stack.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:default_constructor `sym_fiber()`]
|
||||
[variablelist
|
||||
[[Effects:] [Constructs a __sym_fiber__ instance that refers to __not_a_fiber__.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:callable_constructor_stack1 `template< typename Fn > sym_fiber( Fn fn, std::size_t stacksize)`]
|
||||
[variablelist
|
||||
[[Effects:] [`fn` is copied into storage managed internally by the fiber, that
|
||||
copy is invoked on a newly-created fiber.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:callable_constructor_stack2 `template< typename Fn > sym_fiber( Fn fn, std::size_t stacksize, sym_fiber & other)`]
|
||||
[variablelist
|
||||
[[Effects:] [`fn` is copied into storage managed internally by the fiber, that
|
||||
copy is invoked on a newly-created fiber. If `fn` returns `nxt` will be invoked.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:multiple_argument_constructor1 `template< typename Fn, typename A1, typename A2,... > fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize)`]
|
||||
[variablelist
|
||||
[[Preconditions:] [`Fn` and each `A`n must by copyable or movable.]]
|
||||
[[Effects:] [As if `sym_fiber( boost::bind( fn, a1, a2,...) )`. Consequently,
|
||||
`fn` and each `a`n are copied into internal storage for access by the new fiber.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__]]
|
||||
[[Note:] [Currently up to nine additional arguments `a1` to `a9` can be
|
||||
specified in addition to the function `fn`.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:multiple_argument_constructor2 `template< typename Fn, typename A1, typename A2,... > fiber( Fn fn, A1 a1, A2 a2,..., std::size_t stacksize, sym_fiber & nxt)`]
|
||||
[variablelist
|
||||
[[Preconditions:] [`Fn` and each `A`n must by copyable or movable.]]
|
||||
[[Effects:] [As if `sym_fiber( boost::bind( fn, a1, a2,...) )`. Consequently,
|
||||
`fn` and each `a`n are copied into internal storage for access by the new fiber.
|
||||
If `fn` returns `nxt` will be invoked automatically.]]
|
||||
[[Postconditions:] [`*this` refers to the newly created fiber.]]
|
||||
[[Throws:] [__bad_alloc__]]
|
||||
[[Note:] [Currently up to nine additional arguments `a1` to `a9` can be
|
||||
specified in addition to the function `fn`.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:get_id `sym_fiber::id get_id() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers to a fiber, an instance of __sym_fiber_id__ that
|
||||
represents that fiber. Otherwise returns a default-constructed __sym_fiber_id__.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
|
||||
[endsect]
|
||||
|
||||
[section:switch_to `void switch_to( sym_fiber& other)`]
|
||||
[variablelist
|
||||
[[Preconditions:] [`other` and `*this` are not a __not_a_fiber__.]]
|
||||
[[Effects:] [Save current execution context and transfer execution control to
|
||||
`other`.]]
|
||||
[[Throws:] [__fiber_moved__ if `*this` or `other` are __not_a_fiber__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:finished `bool finished() const`]
|
||||
[variablelist
|
||||
[[Effects:] [Returns `true` if fiber has finished.]]
|
||||
[[Throws:] [__fiber_moved__ if `*this` is __not_a_fiber__.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:unspec_operator `operator unspecified-bool-type() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers to a fiber, the function returns true. Otherwise
|
||||
false.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_operator `bool operator!() const`]
|
||||
[variablelist
|
||||
[[Returns:] [If `*this` refers not to a fiber, the function returns true.
|
||||
Otherwise false.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:equals `bool operator==( sym_fiber const& other) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`get_id()==other.get_id()`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_equals `bool operator!=( sym_fiber const& other) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`get_id()!=other.get_id()`]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:swap `void swap( sym_fiber & other)`]
|
||||
[variablelist
|
||||
[[Effects:] [Exchanges the fibers associated with `*this` and `other`, so
|
||||
`*this` is associated with the fiber associated with `other` prior to the call,
|
||||
and vice-versa.]]
|
||||
[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()`
|
||||
prior to the call. `other.get_id()` returns the same value as `this->get_id()`
|
||||
prior to the call.]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:non_member_swap Non-member function `swap()`]
|
||||
|
||||
#include <boost/fiber/sym_fiber.hpp>
|
||||
|
||||
void swap( sym_fiber & lhs, sym_fiber & rhs);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [[link fiber.sym_fiber_management.sym_fiber.swap
|
||||
`lhs.swap( rhs)`].]]
|
||||
[[Throws:] [Nothing.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
|
||||
[section:id Class `boost::sym_fiber::id`]
|
||||
|
||||
#include <boost/fiber/fiber.hpp>
|
||||
|
||||
class sym_fiber::id
|
||||
{
|
||||
public:
|
||||
id();
|
||||
|
||||
bool operator==( id const& y) const;
|
||||
bool operator!=( id const& y) const;
|
||||
bool operator<( id const& y) const;
|
||||
bool operator>( id const& y) const;
|
||||
bool operator<=( id const& y) const;
|
||||
bool operator>=( id const& y) const;
|
||||
|
||||
template< typename charT, typename traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream<charT, traitsT > & os, id const& x);
|
||||
};
|
||||
|
||||
[section:constructor `id()`]
|
||||
[variablelist
|
||||
[[Effects:] [Constructs a __sym_fiber_id__ instance that represents
|
||||
__not_a_fiber__.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:is_equal `bool operator==( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `y` both represent the same fiber of
|
||||
execution, or both represent __not_a_fiber__, `false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:not_equal `bool operator!=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this` and `y` represent different fibers of execution,
|
||||
or one represents a fiber of execution, and the other represent __not_a_fiber__,
|
||||
`false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:less_than `bool operator<( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`true` if `*this!=y` is `true` and the implementation-defined total
|
||||
order of __sym_fiber_id__ values places `*this` before `y`, `false` otherwise.]]
|
||||
[[Throws:] [Nothing]]
|
||||
[[Note:] [A __sym_fiber_id__ instance representing __not_a_fiber__ will alws
|
||||
compare less than an instance representing a fiber of
|
||||
execution.]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:greater_than `bool operator>( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`y<*this`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:less_than_or_equal `bool operator<=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`!(y<*this)`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:greater_than_or_equal `bool operator>=( id const& y) const`]
|
||||
[variablelist
|
||||
[[Returns:] [`!(*this<y)`]]
|
||||
[[Throws:] [Nothing]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[section:stream_out Non-member template function `operator<<`]
|
||||
|
||||
template< typename charT, typename traitsT >
|
||||
friend std::basic_ostream< charT, traitsT > &
|
||||
operator<<( std::basic_ostream<charT, traitsT > & os, id const& x);
|
||||
|
||||
[variablelist
|
||||
[[Effects:] [Writes a representation of the __sym_fiber_id__ instance `x` to
|
||||
the stream `os`, such that the representation of two instances of
|
||||
__sym_fiber_id__ `a` and `b` is the same if `a==b`, and different if `a!=b`.]]
|
||||
[[Returns:] [`os`]]
|
||||
]
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
|
||||
[endsect]
|
||||
@@ -1,24 +0,0 @@
|
||||
# Boost.Fiber Library Examples Jamfile
|
||||
|
||||
# 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)
|
||||
|
||||
# For more information, see http://www.boost.org/
|
||||
|
||||
project boost/fiber/example
|
||||
: requirements
|
||||
<dependency>../../context/build//context.hpp
|
||||
<library>../build//boost_fiber
|
||||
<library>/boost/context//boost_context
|
||||
<library>/boost/thread//boost_thread
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
exe asym_fiber : asym_fiber.cpp ;
|
||||
exe asym_fiber_mt : asym_fiber_mt.cpp ;
|
||||
exe sym_fiber : sym_fiber.cpp ;
|
||||
exe sym_fiber_mt : sym_fiber_mt.cpp ;
|
||||
exe stack : stack.cpp ;
|
||||
@@ -1,47 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value = 0;
|
||||
boost::asym_fiber gf;
|
||||
|
||||
inline
|
||||
void fn( std::string const& str, int n)
|
||||
{
|
||||
for ( int i = 0; i < n; ++i)
|
||||
{
|
||||
std::cout << "asymmetric fiber " << gf.get_id() << ": increment value from " << value << " to ";
|
||||
++value;
|
||||
std::cout << value << std::endl;
|
||||
gf.yield();
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
int n = 5;
|
||||
gf = boost::asym_fiber( fn, "abc", n, boost::asym_fiber::default_stacksize);
|
||||
std::cout << "start" << std::endl;
|
||||
|
||||
while ( ! gf.finished() )
|
||||
{
|
||||
gf.run();
|
||||
std::cout << value << " iteration" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch ( std::exception const& e)
|
||||
{ std::cerr << "exception: " << e.what() << std::endl; }
|
||||
catch (...)
|
||||
{ std::cerr << "unhandled exception" << std::endl; }
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value = 0;
|
||||
boost::asym_fiber gf;
|
||||
|
||||
void increment_value_fn()
|
||||
{
|
||||
while ( true)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << ": increment value from " << value << " to ";
|
||||
++value;
|
||||
std::cout << value << std::endl;
|
||||
gf.yield();
|
||||
}
|
||||
}
|
||||
|
||||
void increment( int k, int n)
|
||||
{
|
||||
for ( int i = k; i < n; ++i)
|
||||
gf.run();
|
||||
}
|
||||
|
||||
void fn_first( int k, int n, boost::barrier & b)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << " executes fiber " << gf.get_id() << std::endl;
|
||||
increment( k, n);
|
||||
b.wait();
|
||||
}
|
||||
|
||||
void fn_last( int k, int n, boost::barrier & b)
|
||||
{
|
||||
b.wait();
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << " executes fiber " << gf.get_id() << std::endl;
|
||||
increment( k, n);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::cout << "start" << std::endl;
|
||||
|
||||
value = 0;
|
||||
|
||||
gf = boost::asym_fiber( increment_value_fn, boost::asym_fiber::default_stacksize);
|
||||
|
||||
boost::barrier b( 2);
|
||||
boost::thread t1( fn_first, 0, 5, boost::ref( b) );
|
||||
boost::thread t2( fn_last, 5, 8, boost::ref( b) );
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch ( std::exception const& e)
|
||||
{ std::cerr << "exception: " << e.what() << std::endl; }
|
||||
catch (...)
|
||||
{ std::cerr << "unhandled exception" << std::endl; }
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::cout << "max stack-size: " << boost::asym_fiber::max_stacksize / 1024 << " kB\n";
|
||||
std::cout << "min stack-size: " << boost::asym_fiber::min_stacksize / 1024 << " kB\n";
|
||||
std::cout << "default stack-size: " << boost::asym_fiber::default_stacksize / 1024 << " kB\n";
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch ( std::exception const& e)
|
||||
{ std::cerr << "exception: " << e.what() << std::endl; }
|
||||
catch (...)
|
||||
{ std::cerr << "unhandled exception" << std::endl; }
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value = 0;
|
||||
boost::sym_fiber gf1;
|
||||
boost::sym_fiber gf2;
|
||||
|
||||
inline
|
||||
void fn( std::string const& str, int n)
|
||||
{
|
||||
for ( int i = 0; i < n; ++i)
|
||||
{
|
||||
std::cout << "symmetric fiber " << gf2.get_id() << ": increment value from " << value << " to ";
|
||||
++value;
|
||||
std::cout << value << std::endl;
|
||||
gf2.switch_to( gf1);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
int n = 5;
|
||||
gf1 = boost::sym_fiber::from_current_context();
|
||||
gf2 = boost::sym_fiber( fn, "abc", n, boost::sym_fiber::default_stacksize, gf1);
|
||||
std::cout << "start" << std::endl;
|
||||
|
||||
while ( ! gf2.finished() )
|
||||
{
|
||||
gf1.switch_to( gf2);
|
||||
std::cout << value << " iteration" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch ( std::exception const& e)
|
||||
{ std::cerr << "exception: " << e.what() << std::endl; }
|
||||
catch (...)
|
||||
{ std::cerr << "unhandled exception" << std::endl; }
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value = 0;
|
||||
boost::sym_fiber gf1;
|
||||
boost::sym_fiber gf2;
|
||||
|
||||
void increment_value_fn()
|
||||
{
|
||||
while ( true)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << ": increment value from " << value << " to ";
|
||||
++value;
|
||||
std::cout << value << std::endl;
|
||||
gf2.switch_to( gf1);
|
||||
}
|
||||
}
|
||||
|
||||
void increment( int k, int n)
|
||||
{
|
||||
gf1 = boost::sym_fiber::from_current_context();
|
||||
for ( int i = k; i < n; ++i)
|
||||
gf1.switch_to( gf2);
|
||||
}
|
||||
|
||||
void fn_first( int k, int n, boost::barrier & b)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << " executes fiber " << gf2.get_id() << std::endl;
|
||||
increment( k, n);
|
||||
b.wait();
|
||||
}
|
||||
|
||||
void fn_last( int k, int n, boost::barrier & b)
|
||||
{
|
||||
b.wait();
|
||||
std::stringstream ss;
|
||||
ss << boost::this_thread::get_id();
|
||||
std::cout << "thread " << ss.str() << " executes fiber " << gf2.get_id() << std::endl;
|
||||
increment( k, n);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::cout << "start" << std::endl;
|
||||
|
||||
value = 0;
|
||||
|
||||
gf2 = boost::sym_fiber( increment_value_fn, boost::sym_fiber::default_stacksize);
|
||||
|
||||
boost::barrier b( 2);
|
||||
boost::thread t1( fn_first, 0, 5, boost::ref( b) );
|
||||
boost::thread t2( fn_last, 5, 8, boost::ref( b) );
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
std::cout << "finish" << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
catch ( std::exception const& e)
|
||||
{ std::cerr << "exception: " << e.what() << std::endl; }
|
||||
catch (...)
|
||||
{ std::cerr << "unhandled exception" << std::endl; }
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#define BOOST_FIBER_SOURCE
|
||||
|
||||
#include <boost/fiber/asym_fiber.hpp>
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/stack_helper.hpp>
|
||||
|
||||
#include <boost/fiber/exceptions.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
std::size_t asym_fiber::max_stacksize = boost::contexts::detail::stack_helper::maximal_stacksize();
|
||||
std::size_t asym_fiber::min_stacksize = boost::contexts::detail::stack_helper::minimal_stacksize();
|
||||
std::size_t asym_fiber::default_stacksize = 256 * 1024;
|
||||
|
||||
asym_fiber::asym_fiber() :
|
||||
impl_()
|
||||
{}
|
||||
|
||||
asym_fiber::asym_fiber( asym_fiber const& other) :
|
||||
impl_( other.impl_)
|
||||
{}
|
||||
|
||||
asym_fiber &
|
||||
asym_fiber::operator=( BOOST_COPY_ASSIGN_REF( asym_fiber) other)
|
||||
{
|
||||
asym_fiber tmp( other);
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
asym_fiber::asym_fiber( BOOST_RV_REF( asym_fiber) other) :
|
||||
impl_()
|
||||
{ swap( other); }
|
||||
|
||||
asym_fiber &
|
||||
asym_fiber::operator=( BOOST_RV_REF( asym_fiber) other)
|
||||
{
|
||||
asym_fiber tmp( boost::move( other) );
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
asym_fiber::operator unspecified_bool_type() const
|
||||
{ return impl_; }
|
||||
|
||||
bool
|
||||
asym_fiber::operator!() const
|
||||
{ return ! impl_; }
|
||||
|
||||
bool
|
||||
asym_fiber::operator==( asym_fiber const& other) const
|
||||
{ return get_id() == other.get_id(); }
|
||||
|
||||
bool
|
||||
asym_fiber::operator!=( asym_fiber const& other) const
|
||||
{ return !( get_id() == other.get_id() ); }
|
||||
|
||||
void
|
||||
asym_fiber::swap( asym_fiber & other)
|
||||
{ impl_.swap( other.impl_); }
|
||||
|
||||
asym_fiber::id
|
||||
asym_fiber::get_id() const
|
||||
{ return asym_fiber::id( impl_); }
|
||||
|
||||
void
|
||||
asym_fiber::run()
|
||||
{
|
||||
if ( ! impl_) throw fiber_moved();
|
||||
BOOST_ASSERT( ! impl_->get_finished() && "fiber already finished");
|
||||
impl_->run();
|
||||
}
|
||||
|
||||
void
|
||||
asym_fiber::yield()
|
||||
{
|
||||
if ( ! impl_) throw fiber_moved();
|
||||
BOOST_ASSERT( ! impl_->get_finished() && "fiber already finished");
|
||||
impl_->yield();
|
||||
}
|
||||
|
||||
bool
|
||||
asym_fiber::finished() const
|
||||
{
|
||||
if ( ! impl_) throw fiber_moved();
|
||||
return impl_->get_finished();
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
@@ -1,82 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#define BOOST_FIBER_SOURCE
|
||||
|
||||
#include <boost/fiber/detail/asym_fiber_base.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4355)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
BOOST_FIBER_DECL void trampoline_asym( void * vp)
|
||||
{
|
||||
BOOST_ASSERT( vp);
|
||||
detail::asym_fiber_base * self(
|
||||
static_cast< detail::asym_fiber_base * >( vp) );
|
||||
try
|
||||
{
|
||||
self->exec();
|
||||
self->set_finished();
|
||||
}
|
||||
catch (...)
|
||||
{ BOOST_ASSERT( false && "exeception from fiber-function"); }
|
||||
}
|
||||
|
||||
asym_fiber_base::do_not_return_t asym_fiber_base::do_not_return;
|
||||
asym_fiber_base::do_return_t asym_fiber_base::do_return;
|
||||
|
||||
asym_fiber_base::asym_fiber_base( std::size_t stacksize, do_not_return_t) :
|
||||
use_count_( 0),
|
||||
finished_( false),
|
||||
caller_(),
|
||||
callee_( trampoline_asym, this, protected_stack( stacksize) )
|
||||
{}
|
||||
|
||||
asym_fiber_base::asym_fiber_base( std::size_t stacksize, do_return_t) :
|
||||
use_count_( 0),
|
||||
finished_( false),
|
||||
caller_(),
|
||||
callee_( trampoline_asym, caller_, this, protected_stack( stacksize) )
|
||||
{}
|
||||
|
||||
void
|
||||
asym_fiber_base::run()
|
||||
{ caller_.jump_to( callee_); }
|
||||
|
||||
void
|
||||
asym_fiber_base::yield()
|
||||
{ callee_.jump_to( caller_); }
|
||||
|
||||
void
|
||||
asym_fiber_base::set_finished()
|
||||
{ finished_ = true; }
|
||||
|
||||
bool
|
||||
asym_fiber_base::get_finished() const
|
||||
{ return finished_; }
|
||||
|
||||
}}}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#define BOOST_FIBER_SOURCE
|
||||
|
||||
#include <boost/fiber/detail/sym_fiber_base.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4355)
|
||||
# endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
namespace detail {
|
||||
|
||||
BOOST_FIBER_DECL void trampoline_sym( void * vp)
|
||||
{
|
||||
BOOST_ASSERT( vp);
|
||||
detail::sym_fiber_base * self(
|
||||
static_cast< detail::sym_fiber_base * >( vp) );
|
||||
try
|
||||
{
|
||||
self->exec();
|
||||
self->set_finished();
|
||||
}
|
||||
catch (...)
|
||||
{ BOOST_ASSERT( false && "exeception from fiber-function"); }
|
||||
}
|
||||
|
||||
sym_fiber_base::sym_fiber_base() :
|
||||
use_count_( 0),
|
||||
finished_( false),
|
||||
ctx_()
|
||||
{}
|
||||
|
||||
sym_fiber_base::sym_fiber_base( std::size_t stacksize) :
|
||||
use_count_( 0),
|
||||
finished_( false),
|
||||
ctx_( trampoline_sym, this, protected_stack( stacksize) )
|
||||
{}
|
||||
|
||||
sym_fiber_base::sym_fiber_base( std::size_t stacksize, sym_fiber_base & nxt) :
|
||||
use_count_( 0),
|
||||
finished_( false),
|
||||
ctx_( trampoline_sym, nxt.ctx_, this, protected_stack( stacksize) )
|
||||
{}
|
||||
|
||||
void
|
||||
sym_fiber_base::switch_to( sym_fiber_base & other)
|
||||
{ ctx_.jump_to( other.ctx_); }
|
||||
|
||||
void
|
||||
sym_fiber_base::set_finished()
|
||||
{ finished_ = true; }
|
||||
|
||||
bool
|
||||
sym_fiber_base::get_finished() const
|
||||
{ return finished_; }
|
||||
|
||||
}}}
|
||||
|
||||
# if defined(BOOST_MSVC)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
|
||||
// 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)
|
||||
|
||||
#define BOOST_FIBER_SOURCE
|
||||
|
||||
#include <boost/fiber/sym_fiber.hpp>
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/context/detail/stack_helper.hpp>
|
||||
|
||||
#include <boost/fiber/exceptions.hpp>
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_PREFIX
|
||||
#endif
|
||||
|
||||
namespace boost {
|
||||
namespace fibers {
|
||||
|
||||
std::size_t sym_fiber::max_stacksize = boost::contexts::detail::stack_helper::maximal_stacksize();
|
||||
std::size_t sym_fiber::min_stacksize = boost::contexts::detail::stack_helper::minimal_stacksize();
|
||||
std::size_t sym_fiber::default_stacksize = 256 * 1024;
|
||||
|
||||
sym_fiber
|
||||
sym_fiber::from_current_context()
|
||||
{ return sym_fiber( new detail::sym_fiber_dummy() ); }
|
||||
|
||||
sym_fiber::sym_fiber() :
|
||||
impl_()
|
||||
{}
|
||||
|
||||
sym_fiber::sym_fiber( detail::sym_fiber_base::ptr const& impl) :
|
||||
impl_( impl)
|
||||
{}
|
||||
|
||||
sym_fiber::sym_fiber( sym_fiber const& other) :
|
||||
impl_( other.impl_)
|
||||
{}
|
||||
|
||||
sym_fiber &
|
||||
sym_fiber::operator=( BOOST_COPY_ASSIGN_REF( sym_fiber) other)
|
||||
{
|
||||
sym_fiber tmp( other);
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
sym_fiber::sym_fiber( BOOST_RV_REF( sym_fiber) other) :
|
||||
impl_()
|
||||
{ swap( other); }
|
||||
|
||||
sym_fiber &
|
||||
sym_fiber::operator=( BOOST_RV_REF( sym_fiber) other)
|
||||
{
|
||||
sym_fiber tmp( boost::move( other) );
|
||||
swap( tmp);
|
||||
return * this;
|
||||
}
|
||||
|
||||
sym_fiber::operator unspecified_bool_type() const
|
||||
{ return impl_; }
|
||||
|
||||
bool
|
||||
sym_fiber::operator!() const
|
||||
{ return ! impl_; }
|
||||
|
||||
bool
|
||||
sym_fiber::operator==( sym_fiber const& other) const
|
||||
{ return get_id() == other.get_id(); }
|
||||
|
||||
bool
|
||||
sym_fiber::operator!=( sym_fiber const& other) const
|
||||
{ return !( get_id() == other.get_id() ); }
|
||||
|
||||
void
|
||||
sym_fiber::swap( sym_fiber & other)
|
||||
{ impl_.swap( other.impl_); }
|
||||
|
||||
sym_fiber::id
|
||||
sym_fiber::get_id() const
|
||||
{ return sym_fiber::id( impl_); }
|
||||
|
||||
void
|
||||
sym_fiber::switch_to( sym_fiber & other)
|
||||
{
|
||||
if ( ! impl_ || ! other) throw fiber_moved();
|
||||
BOOST_ASSERT( ! impl_->get_finished() && "fiber already finished");
|
||||
BOOST_ASSERT( ! other.finished() && "fiber already finished");
|
||||
impl_->switch_to( * other.impl_);
|
||||
}
|
||||
|
||||
bool
|
||||
sym_fiber::finished() const
|
||||
{
|
||||
if ( ! impl_) throw fiber_moved();
|
||||
return impl_->get_finished();
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#ifdef BOOST_HAS_ABI_HEADERS
|
||||
# include BOOST_ABI_SUFFIX
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
# Boost.fiber Library Tests Jamfile
|
||||
|
||||
# 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)
|
||||
|
||||
import testing ;
|
||||
|
||||
project boost/fiber/test
|
||||
: requirements
|
||||
<dependency>../../context/build//context.hpp
|
||||
<library>../../test/build//boost_unit_test_framework
|
||||
<library>/boost/context//boost_context
|
||||
<library>/boost/fiber//boost_fiber
|
||||
<library>/boost/thread//boost_thread
|
||||
<link>static
|
||||
<threading>multi
|
||||
;
|
||||
|
||||
rule test ( source )
|
||||
{
|
||||
return
|
||||
[ run $(source).cpp ]
|
||||
;
|
||||
}
|
||||
|
||||
test-suite fiber :
|
||||
[ test test_asym_fiber ]
|
||||
[ test test_sym_fiber ]
|
||||
;
|
||||
@@ -1,228 +0,0 @@
|
||||
|
||||
// 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 <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value;
|
||||
|
||||
boost::asym_fiber gf;
|
||||
|
||||
void zero_args_fn()
|
||||
{}
|
||||
|
||||
void one_args_fn( int)
|
||||
{}
|
||||
|
||||
void two_args_fn( int, std::string const&)
|
||||
{}
|
||||
|
||||
void set_value_fn( int i)
|
||||
{ value = i; }
|
||||
|
||||
void increment_value_fn()
|
||||
{
|
||||
while ( true)
|
||||
{
|
||||
++value;
|
||||
gf.yield();
|
||||
}
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
void operator()()
|
||||
{}
|
||||
};
|
||||
|
||||
struct Y
|
||||
{
|
||||
void operator()( int i)
|
||||
{}
|
||||
};
|
||||
|
||||
void increment( int k, int n)
|
||||
{
|
||||
for ( int i = k; i < n; ++i)
|
||||
{
|
||||
gf.run();
|
||||
BOOST_CHECK_EQUAL( i + 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
void fn_first( int k, int n, boost::barrier & b)
|
||||
{
|
||||
increment( k, n);
|
||||
b.wait();
|
||||
}
|
||||
|
||||
void fn_last( int k, int n, boost::barrier & b)
|
||||
{
|
||||
b.wait();
|
||||
increment( k, n);
|
||||
}
|
||||
|
||||
void test_case_1()
|
||||
{
|
||||
X x;
|
||||
boost::asym_fiber f1( & X::operator(), x, boost::asym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f1);
|
||||
|
||||
Y y;
|
||||
boost::asym_fiber f2( & Y::operator(), y, 7, boost::asym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f2);
|
||||
}
|
||||
|
||||
void test_case_2()
|
||||
{
|
||||
boost::asym_fiber f1( one_args_fn, 10, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f2;
|
||||
BOOST_CHECK( f1);
|
||||
BOOST_CHECK( ! f2);
|
||||
}
|
||||
|
||||
void test_case_3()
|
||||
{
|
||||
boost::asym_fiber f1( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f2( one_args_fn, 1, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f3( two_args_fn, 1, "abc", boost::asym_fiber::default_stacksize);
|
||||
}
|
||||
|
||||
void test_case_4()
|
||||
{
|
||||
boost::asym_fiber f1( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
f1 = boost::asym_fiber( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f2( one_args_fn, 1, boost::asym_fiber::default_stacksize);
|
||||
f2 = boost::asym_fiber( one_args_fn, 1, boost::asym_fiber::default_stacksize);
|
||||
}
|
||||
|
||||
void test_case_5()
|
||||
{
|
||||
boost::asym_fiber f1( one_args_fn, 10, boost::asym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f1);
|
||||
boost::asym_fiber f2( boost::move( f1) );
|
||||
BOOST_CHECK( ! f1);
|
||||
BOOST_CHECK( f2);
|
||||
boost::asym_fiber f3;
|
||||
BOOST_CHECK( ! f3);
|
||||
f3 = f2;
|
||||
BOOST_CHECK( f3);
|
||||
BOOST_CHECK_EQUAL( f2, f3);
|
||||
}
|
||||
|
||||
void test_case_6()
|
||||
{
|
||||
boost::asym_fiber f1( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f2( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f3;
|
||||
BOOST_CHECK( f1);
|
||||
BOOST_CHECK( f2);
|
||||
BOOST_CHECK( ! f3);
|
||||
|
||||
BOOST_CHECK( f1 != f2);
|
||||
BOOST_CHECK( f1 != f3);
|
||||
BOOST_CHECK( f2 != f3);
|
||||
|
||||
std::ostringstream os1;
|
||||
os1 << f1.get_id();
|
||||
std::ostringstream os2;
|
||||
os2 << f2.get_id();
|
||||
std::ostringstream os3;
|
||||
os3 << f3.get_id();
|
||||
|
||||
std::string not_a_fiber("{not-a-fiber}");
|
||||
BOOST_CHECK( os1.str() != os2.str() );
|
||||
BOOST_CHECK( os1.str() != os3.str() );
|
||||
BOOST_CHECK( os2.str() != os3.str() );
|
||||
BOOST_CHECK( os1.str() != not_a_fiber);
|
||||
BOOST_CHECK( os2.str() != not_a_fiber);
|
||||
BOOST_CHECK( os3.str() == not_a_fiber);
|
||||
}
|
||||
|
||||
void test_case_7()
|
||||
{
|
||||
boost::asym_fiber f1( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
boost::asym_fiber f2( zero_args_fn, boost::asym_fiber::default_stacksize);
|
||||
|
||||
boost::asym_fiber::id id1 = f1.get_id();
|
||||
boost::asym_fiber::id id2 = f2.get_id();
|
||||
|
||||
f1.swap( f2);
|
||||
|
||||
BOOST_CHECK_EQUAL( f1.get_id(), id2);
|
||||
BOOST_CHECK_EQUAL( f2.get_id(), id1);
|
||||
}
|
||||
|
||||
void test_case_8()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
boost::asym_fiber f( set_value_fn, 7, boost::asym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
f.run();
|
||||
|
||||
BOOST_CHECK_EQUAL( 7, value);
|
||||
}
|
||||
|
||||
void test_case_9()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
gf = boost::asym_fiber( increment_value_fn, boost::asym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
for ( int i = 0; i < 7; ++i)
|
||||
{
|
||||
gf.run();
|
||||
BOOST_CHECK_EQUAL( i + 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
void test_case_10()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
gf = boost::asym_fiber( increment_value_fn, boost::asym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
boost::barrier b( 2);
|
||||
boost::thread t1( fn_first, 0, 5, boost::ref( b) );
|
||||
boost::thread t2( fn_last, 5, 7, boost::ref( b) );
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
BOOST_CHECK_EQUAL( 7, value);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
|
||||
{
|
||||
boost::unit_test::test_suite * test =
|
||||
BOOST_TEST_SUITE("Boost.Fiber: fiber test suite");
|
||||
|
||||
test->add( BOOST_TEST_CASE( & test_case_1) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_2) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_3) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_4) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_5) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_6) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_7) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_8) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_9) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_10) );
|
||||
|
||||
return test;
|
||||
}
|
||||
@@ -1,235 +0,0 @@
|
||||
|
||||
// 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 <sstream>
|
||||
#include <string>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
#include <boost/fiber/all.hpp>
|
||||
|
||||
int value;
|
||||
|
||||
boost::sym_fiber gf1;
|
||||
boost::sym_fiber gf2;
|
||||
|
||||
void zero_args_fn()
|
||||
{}
|
||||
|
||||
void one_args_fn( int)
|
||||
{}
|
||||
|
||||
void two_args_fn( int, std::string const&)
|
||||
{}
|
||||
|
||||
void set_value_fn( int i)
|
||||
{
|
||||
value = i;
|
||||
gf2.switch_to( gf1);
|
||||
}
|
||||
|
||||
void increment_value_fn()
|
||||
{
|
||||
while ( true)
|
||||
{
|
||||
++value;
|
||||
gf2.switch_to( gf1);
|
||||
}
|
||||
}
|
||||
|
||||
struct X
|
||||
{
|
||||
void operator()()
|
||||
{}
|
||||
};
|
||||
|
||||
struct Y
|
||||
{
|
||||
void operator()( int i)
|
||||
{}
|
||||
};
|
||||
|
||||
void increment( int k, int n)
|
||||
{
|
||||
gf1 = boost::sym_fiber::from_current_context();
|
||||
for ( int i = k; i < n; ++i)
|
||||
{
|
||||
gf1.switch_to( gf2);
|
||||
BOOST_CHECK_EQUAL( i + 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
void fn_first( int k, int n, boost::barrier & b)
|
||||
{
|
||||
increment( k, n);
|
||||
b.wait();
|
||||
}
|
||||
|
||||
void fn_last( int k, int n, boost::barrier & b)
|
||||
{
|
||||
b.wait();
|
||||
increment( k, n);
|
||||
}
|
||||
|
||||
void test_case_1()
|
||||
{
|
||||
X x;
|
||||
boost::sym_fiber f1( & X::operator(), x, boost::sym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f1);
|
||||
|
||||
Y y;
|
||||
boost::sym_fiber f2( & Y::operator(), y, 7, boost::sym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f2);
|
||||
}
|
||||
|
||||
void test_case_2()
|
||||
{
|
||||
boost::sym_fiber f1( one_args_fn, 10, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f2;
|
||||
BOOST_CHECK( f1);
|
||||
BOOST_CHECK( ! f2);
|
||||
}
|
||||
|
||||
void test_case_3()
|
||||
{
|
||||
boost::sym_fiber f1( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f2( one_args_fn, 1, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f3( two_args_fn, 1, "abc", boost::sym_fiber::default_stacksize);
|
||||
}
|
||||
|
||||
void test_case_4()
|
||||
{
|
||||
boost::sym_fiber f1( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
f1 = boost::sym_fiber( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f2( one_args_fn, 1, boost::sym_fiber::default_stacksize);
|
||||
f2 = boost::sym_fiber( one_args_fn, 1, boost::sym_fiber::default_stacksize);
|
||||
}
|
||||
|
||||
void test_case_5()
|
||||
{
|
||||
boost::sym_fiber f1( one_args_fn, 10, boost::sym_fiber::default_stacksize);
|
||||
BOOST_CHECK( f1);
|
||||
boost::sym_fiber f2( boost::move( f1) );
|
||||
BOOST_CHECK( ! f1);
|
||||
BOOST_CHECK( f2);
|
||||
boost::sym_fiber f3;
|
||||
BOOST_CHECK( ! f3);
|
||||
f3 = f2;
|
||||
BOOST_CHECK( f3);
|
||||
BOOST_CHECK_EQUAL( f2, f3);
|
||||
}
|
||||
|
||||
void test_case_6()
|
||||
{
|
||||
boost::sym_fiber f1( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f2( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f3;
|
||||
BOOST_CHECK( f1);
|
||||
BOOST_CHECK( f2);
|
||||
BOOST_CHECK( ! f3);
|
||||
|
||||
BOOST_CHECK( f1 != f2);
|
||||
BOOST_CHECK( f1 != f3);
|
||||
BOOST_CHECK( f2 != f3);
|
||||
|
||||
std::ostringstream os1;
|
||||
os1 << f1.get_id();
|
||||
std::ostringstream os2;
|
||||
os2 << f2.get_id();
|
||||
std::ostringstream os3;
|
||||
os3 << f3.get_id();
|
||||
|
||||
std::string not_a_fiber("{not-a-fiber}");
|
||||
BOOST_CHECK( os1.str() != os2.str() );
|
||||
BOOST_CHECK( os1.str() != os3.str() );
|
||||
BOOST_CHECK( os2.str() != os3.str() );
|
||||
BOOST_CHECK( os1.str() != not_a_fiber);
|
||||
BOOST_CHECK( os2.str() != not_a_fiber);
|
||||
BOOST_CHECK( os3.str() == not_a_fiber);
|
||||
}
|
||||
|
||||
void test_case_7()
|
||||
{
|
||||
boost::sym_fiber f1( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
boost::sym_fiber f2( zero_args_fn, boost::sym_fiber::default_stacksize);
|
||||
|
||||
boost::sym_fiber::id id1 = f1.get_id();
|
||||
boost::sym_fiber::id id2 = f2.get_id();
|
||||
|
||||
f1.swap( f2);
|
||||
|
||||
BOOST_CHECK_EQUAL( f1.get_id(), id2);
|
||||
BOOST_CHECK_EQUAL( f2.get_id(), id1);
|
||||
}
|
||||
|
||||
void test_case_8()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
gf1 = boost::sym_fiber::from_current_context();
|
||||
gf2 = boost::sym_fiber( set_value_fn, 7, boost::sym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
gf1.switch_to( gf2);
|
||||
|
||||
BOOST_CHECK_EQUAL( 7, value);
|
||||
}
|
||||
|
||||
void test_case_9()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
gf1 = boost::sym_fiber::from_current_context();
|
||||
gf2 = boost::sym_fiber( increment_value_fn, boost::sym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
for ( int i = 0; i < 7; ++i)
|
||||
{
|
||||
gf1.switch_to( gf2);
|
||||
BOOST_CHECK_EQUAL( i + 1, value);
|
||||
}
|
||||
}
|
||||
|
||||
void test_case_10()
|
||||
{
|
||||
value = 0;
|
||||
|
||||
gf2 = boost::sym_fiber( increment_value_fn, boost::sym_fiber::default_stacksize);
|
||||
|
||||
BOOST_CHECK_EQUAL( 0, value);
|
||||
|
||||
boost::barrier b( 2);
|
||||
boost::thread t1( fn_first, 0, 5, boost::ref( b) );
|
||||
boost::thread t2( fn_last, 5, 7, boost::ref( b) );
|
||||
t1.join();
|
||||
t2.join();
|
||||
|
||||
BOOST_CHECK_EQUAL( 7, value);
|
||||
}
|
||||
|
||||
boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
|
||||
{
|
||||
boost::unit_test::test_suite * test =
|
||||
BOOST_TEST_SUITE("Boost.Fiber: fiber test suite");
|
||||
|
||||
test->add( BOOST_TEST_CASE( & test_case_1) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_2) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_3) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_4) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_5) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_6) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_7) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_8) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_9) );
|
||||
test->add( BOOST_TEST_CASE( & test_case_10) );
|
||||
|
||||
return test;
|
||||
}
|
||||
Reference in New Issue
Block a user