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

changed directory structure as required by modularized-boost

This commit is contained in:
Oliver Kowalke
2012-12-09 15:22:59 +01:00
parent de1188faa2
commit 81e62e8962
77 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,23 @@
// 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_H
#define BOOST_FIBERS_H
#include <boost/fiber/auto_reset_event.hpp>
#include <boost/fiber/barrier.hpp>
#include <boost/fiber/bounded_channel.hpp>
#include <boost/fiber/condition.hpp>
#include <boost/fiber/count_down_event.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/future.hpp>
#include <boost/fiber/manual_reset_event.hpp>
#include <boost/fiber/mutex.hpp>
#include <boost/fiber/operations.hpp>
#include <boost/fiber/fiber.hpp>
#include <boost/fiber/unbounded_channel.hpp>
#endif // BOOST_FIBERS_H

View File

@@ -0,0 +1,85 @@
// 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_ATTRIBUTES_H
#define BOOST_FIBERS_ATTRIBUTES_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/fiber/flags.hpp>
#include <boost/fiber/stack_allocator.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
struct attributes
{
std::size_t size;
flag_unwind_t do_unwind;
flag_fpu_t preserve_fpu;
attributes() BOOST_NOEXCEPT :
size( stack_allocator::default_stacksize() ),
do_unwind( stack_unwind),
preserve_fpu( fpu_preserved)
{}
explicit attributes( std::size_t size_) BOOST_NOEXCEPT :
size( size_),
do_unwind( stack_unwind),
preserve_fpu( fpu_preserved)
{}
explicit attributes( flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( stack_allocator::default_stacksize() ),
do_unwind( do_unwind_),
preserve_fpu( fpu_preserved)
{}
explicit attributes( flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
size( stack_allocator::default_stacksize() ),
do_unwind( stack_unwind),
preserve_fpu( preserve_fpu_)
{}
explicit attributes(
std::size_t size_,
flag_unwind_t do_unwind_) BOOST_NOEXCEPT :
size( size_),
do_unwind( do_unwind_),
preserve_fpu( fpu_preserved)
{}
explicit attributes(
std::size_t size_,
flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
size( size_),
do_unwind( stack_unwind),
preserve_fpu( preserve_fpu_)
{}
explicit attributes(
flag_unwind_t do_unwind_,
flag_fpu_t preserve_fpu_) BOOST_NOEXCEPT :
size( stack_allocator::default_stacksize() ),
do_unwind( do_unwind_),
preserve_fpu( preserve_fpu_)
{}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_ATTRIBUTES_H

View File

@@ -0,0 +1,71 @@
// 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_AUTO_RESET_EVENT_H
#define BOOST_FIBERS_AUTO_RESET_EVENT_H
#include <deque>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355 4251 4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL auto_reset_event : private noncopyable
{
private:
enum state
{
SET = 0,
RESET
};
state state_;
std::deque<
detail::fiber_base::ptr_t
> waiting_;
public:
explicit auto_reset_event( bool = false);
void wait();
template< typename TimeDuration >
bool timed_wait( TimeDuration const& dt)
{ return timed_wait( chrono::system_clock::now() + dt); }
bool timed_wait( chrono::system_clock::time_point const& abs_time);
bool try_wait();
void set();
};
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_AUTO_RESET_EVENT_H

View File

@@ -0,0 +1,56 @@
// 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_BARRIER_H
#define BOOST_FIBERS_BARRIER_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/condition.hpp>
#include <boost/fiber/mutex.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL barrier : private noncopyable
{
private:
std::size_t initial_;
std::size_t current_;
bool cycle_;
mutex mtx_;
condition cond_;
public:
barrier( std::size_t);
bool wait();
};
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_BARRIER_H

View File

@@ -0,0 +1,328 @@
// 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)
//
// idea of node-base locking from 'C++ Concurrency in Action', Anthony Williams
#ifndef BOOST_FIBERS_BOUNDED_CHANNEL_H
#define BOOST_FIBERS_BOUNDED_CHANNEL_H
#include <cstddef>
#include <stdexcept>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/condition.hpp>
#include <boost/fiber/mutex.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
template< typename T >
struct bounded_channel_node
{
typedef intrusive_ptr< bounded_channel_node > ptr;
std::size_t use_count;
T va;
ptr next;
bounded_channel_node() :
use_count( 0),
va(),
next()
{}
};
template< typename T >
void intrusive_ptr_add_ref( bounded_channel_node< T > * p)
{ ++p->use_count; }
template< typename T >
void intrusive_ptr_release( bounded_channel_node< T > * p)
{ if ( 0 == --p->use_count) delete p; }
}
template< typename T >
class bounded_channel : private noncopyable
{
public:
typedef optional< T > value_type;
private:
typedef detail::bounded_channel_node< value_type > node_type;
template< typename X >
friend void intrusive_ptr_add_ref( bounded_channel< X > * p);
template< typename X >
friend void intrusive_ptr_release( bounded_channel< X > * p);
enum state
{
ACTIVE = 0,
DEACTIVE
};
state state_;
std::size_t count_;
typename node_type::ptr head_;
mutable mutex head_mtx_;
typename node_type::ptr tail_;
mutable mutex tail_mtx_;
condition not_empty_cond_;
condition not_full_cond_;
unsigned int hwm_;
unsigned int lwm_;
bool active_() const
{ return ACTIVE == state_; }
void deactivate_()
{ state_ = DEACTIVE; }
std::size_t size_() const
{ return count_; }
bool empty_() const
{ return head_ == get_tail_(); }
bool full_() const
{ return size_() >= hwm_; }
typename node_type::ptr get_tail_() const
{
mutex::scoped_lock lk( tail_mtx_);
typename node_type::ptr tmp = tail_;
return tmp;
}
typename node_type::ptr pop_head_()
{
typename node_type::ptr old_head = head_;
head_ = old_head->next;
--count_;
return old_head;
}
public:
bounded_channel(
std::size_t hwm,
std::size_t lwm) :
state_( ACTIVE),
count_( 0),
head_( new node_type() ),
head_mtx_(),
tail_( head_),
tail_mtx_(),
not_empty_cond_(),
not_full_cond_(),
hwm_( hwm),
lwm_( lwm)
{
if ( hwm_ < lwm_)
throw invalid_watermark();
}
bounded_channel( std::size_t wm) :
state_( ACTIVE),
count_( 0),
head_( new node_type() ),
head_mtx_(),
tail_( head_),
tail_mtx_(),
not_empty_cond_(),
not_full_cond_(),
hwm_( wm),
lwm_( wm)
{}
std::size_t upper_bound() const
{ return hwm_; }
std::size_t lower_bound() const
{ return lwm_; }
bool active() const
{ return active_(); }
void deactivate()
{
mutex::scoped_lock head_lk( head_mtx_);
mutex::scoped_lock tail_lk( tail_mtx_);
deactivate_();
not_empty_cond_.notify_all();
not_full_cond_.notify_all();
}
bool empty() const
{
mutex::scoped_lock lk( head_mtx_);
return empty_();
}
void put( T const& t)
{
typename node_type::ptr new_node( new node_type() );
{
mutex::scoped_lock lk( tail_mtx_);
if ( full_() )
{
while ( active_() && full_() )
not_full_cond_.wait( lk);
}
if ( ! active_() )
throw std::runtime_error("queue is not active");
tail_->va = t;
tail_->next = new_node;
tail_ = new_node;
++count_;
}
not_empty_cond_.notify_one();
}
template< typename TimeDuration >
bool put( T const& t, TimeDuration const& dt)
{ return put( t, chrono::system_clock::now() + dt); }
bool put( T const& t, chrono::system_clock::time_point const& abs_time)
{
typename node_type::ptr new_node( new node_type() );
{
mutex::scoped_lock lk( tail_mtx_);
if ( full_() )
{
while ( active_() && full_() )
{
if ( ! not_full_cond_.timed_wait( lk, abs_time) )
return false;
}
}
if ( ! active_() )
throw std::runtime_error("queue is not active");
tail_->va = t;
tail_->next = new_node;
tail_ = new_node;
++count_;
}
not_empty_cond_.notify_one();
return true;
}
bool take( value_type & va)
{
mutex::scoped_lock lk( head_mtx_);
bool empty = empty_();
if ( ! active_() && empty)
return false;
if ( empty)
{
// try
// {
while ( active_() && empty_() )
not_empty_cond_.wait( lk);
// }
// catch ( fibers_interrupted const&)
// { return false; }
}
if ( ! active_() && empty_() )
return false;
swap( va, head_->va);
pop_head_();
if ( size_() <= lwm_)
{
if ( lwm_ == hwm_)
not_full_cond_.notify_one();
else
// more than one producer could be waiting
// for submiting an action object
not_full_cond_.notify_all();
}
return va;
}
template< typename TimeDuration >
bool take( value_type & va, TimeDuration const& dt)
{ return take( va, chrono::system_clock::now() + dt); }
bool take( value_type & va, chrono::system_clock::time_point const& abs_time)
{
mutex::scoped_lock lk( head_mtx_);
bool empty = empty_();
if ( ! active_() && empty)
return false;
if ( empty)
{
// try
// {
while ( active_() && empty_() )
{
if ( ! not_empty_cond_.timed_wait( lk, abs_time) )
return false;
}
// }
// catch ( fibers_interrupted const&)
// { return false; }
}
if ( ! active_() && empty_() )
return false;
swap( va, head_->va);
pop_head_();
if ( size_() <= lwm_)
{
if ( lwm_ == hwm_)
not_full_cond_.notify_one();
else
// more than one producer could be waiting
// for submiting an action object
not_full_cond_.notify_all();
}
return va;
}
bool try_take( value_type & va)
{
mutex::scoped_lock lk( head_mtx_);
if ( empty_() )
return false;
swap( va, head_->va);
pop_head_();
bool valid = va;
if ( valid && size_() <= lwm_)
{
if ( lwm_ == hwm_)
not_full_cond_.notify_one();
else
// more than one producer could be waiting
// in order to submit an task
not_full_cond_.notify_all();
}
return valid;
}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_BOUNDED_CHANNEL_H

View File

@@ -0,0 +1,230 @@
// 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)
//
// based on boost::interprocess::sync::interprocess_condition
#ifndef BOOST_FIBERS_CONDITION_H
#define BOOST_FIBERS_CONDITION_H
#include <cstddef>
#include <deque>
#include <boost/assert.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/scheduler.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/mutex.hpp>
#include <boost/fiber/operations.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355 4251 4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL condition : private noncopyable
{
private:
enum command
{
SLEEPING = 0,
NOTIFY_ONE,
NOTIFY_ALL
};
command cmd_;
std::size_t waiters_;
mutex enter_mtx_;
mutex check_mtx_;
std::deque<
detail::fiber_base::ptr_t
> waiting_;
public:
condition();
~condition();
void notify_one();
void notify_all();
template< typename LockType, typename Pred >
void wait( LockType & lt, Pred pred)
{
while ( ! pred() )
wait( lt);
}
template< typename LockType >
void wait( LockType & lt)
{
{
mutex::scoped_lock lk( enter_mtx_);
BOOST_ASSERT( lk);
++waiters_;
lt.unlock();
}
bool unlock_enter_mtx = false;
for (;;)
{
while ( SLEEPING == cmd_)
{
if ( this_fiber::is_fiberized() )
{
waiting_.push_back(
detail::scheduler::instance().active() );
detail::scheduler::instance().wait();
}
else
detail::scheduler::instance().run();
}
if ( NOTIFY_ONE == cmd_)
{
unlock_enter_mtx = true;
--waiters_;
cmd_ = SLEEPING;
break;
}
else
{
unlock_enter_mtx = 0 == --waiters_;
if ( unlock_enter_mtx)
cmd_ = SLEEPING;
break;
}
}
if ( unlock_enter_mtx)
enter_mtx_.unlock();
lt.lock();
}
template< typename LockType, typename TimeDuration >
bool timed_wait( LockType & lt, TimeDuration const& dt)
{ return timed_wait( lt, chrono::system_clock::now() + dt); }
template< typename LockType, typename TimeDuration, typename Pred >
bool timed_wait( LockType & lt, TimeDuration const& dt, Pred pred)
{ return timed_wait( lt, chrono::system_clock::now() + dt, pred); }
template< typename LockType, typename Pred >
bool timed_wait( LockType & lt, chrono::system_clock::time_point const& abs_time, Pred pred)
{
while ( ! pred() )
if ( ! timed_wait( lt, abs_time) )
return pred();
return true;
}
template< typename LockType >
bool timed_wait( LockType & lt, chrono::system_clock::time_point const& abs_time)
{
if ( (chrono::system_clock::time_point::max)() == abs_time){
wait( lt);
return true;
}
chrono::system_clock::time_point now( chrono::system_clock::now() );
if ( now >= abs_time) return false;
{
mutex::scoped_lock lk( enter_mtx_);
BOOST_ASSERT( lk);
++waiters_;
lt.unlock();
}
bool unlock_enter_mtx = false, timed_out = false;
for (;;)
{
while ( SLEEPING == cmd_)
{
now = chrono::system_clock::now();
if ( now >= abs_time)
{
while ( ! ( timed_out = enter_mtx_.try_lock() ) )
detail::scheduler::instance().yield();
break;
}
if ( this_fiber::is_fiberized() )
{
waiting_.push_back(
detail::scheduler::instance().active() );
detail::scheduler::instance().sleep( abs_time);
}
else
detail::scheduler::instance().run();
now = chrono::system_clock::now();
if ( now >= abs_time)
{
while ( ! ( timed_out = enter_mtx_.try_lock() ) )
detail::scheduler::instance().yield();
break;
}
}
if ( timed_out)
{
unlock_enter_mtx = true;
--waiters_;
break;
}
if ( NOTIFY_ONE == cmd_)
{
unlock_enter_mtx = true;
--waiters_;
cmd_ = SLEEPING;
break;
}
else
{
unlock_enter_mtx = 0 == --waiters_;
if ( unlock_enter_mtx)
cmd_ = SLEEPING;
break;
}
}
if ( unlock_enter_mtx)
enter_mtx_.unlock();
lt.lock();
return ! timed_out;
}
};
typedef condition condition_variable;
typedef condition condition_variable_any;
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_CONDITION_H

View File

@@ -0,0 +1,71 @@
// 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_COUNT_DOWN_EVENT_H
#define BOOST_FIBERS_COUNT_DOWN_EVENT_H
#include <cstddef>
#include <deque>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355 4251 4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL count_down_event : private noncopyable
{
private:
std::size_t initial_;
std::size_t current_;
std::deque<
detail::fiber_base::ptr_t
> waiting_;
public:
explicit count_down_event( std::size_t);
std::size_t initial() const;
std::size_t current() const;
void wait();
template< typename TimeDuration >
bool timed_wait( TimeDuration const& dt)
{ return timed_wait( chrono::system_clock::now() + dt); }
bool timed_wait( chrono::system_clock::time_point const& abs_time);
bool is_set() const;
void set();
};
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_COUNT_DOWN_EVENT_H

View File

@@ -0,0 +1,42 @@
// 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_CONFIG_H
#define BOOST_FIBERS_DETAIL_CONFIG_H
#include <boost/config.hpp>
#include <boost/detail/workaround.hpp>
#ifdef BOOST_FIBERS_DECL
# undef BOOST_FIBERS_DECL
#endif
#if defined(BOOST_HAS_DECLSPEC)
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FIBERS_DYN_LINK)
# if ! defined(BOOST_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# if defined(BOOST_FIBERS_SOURCE)
# define BOOST_FIBERS_DECL BOOST_SYMBOL_EXPORT
# else
# define BOOST_FIBERS_DECL BOOST_SYMBOL_IMPORT
# endif
# endif
#endif
#if ! defined(BOOST_FIBERS_DECL)
# define BOOST_FIBERS_DECL
#endif
#if ! defined(BOOST_FIBERS_SOURCE) && ! defined(BOOST_ALL_NO_LIB) && ! defined(BOOST_FIBERS_NO_LIB)
# define BOOST_LIB_NAME boost_context
# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FIBERS_DYN_LINK)
# define BOOST_DYN_LINK
# endif
# include <boost/config/auto_link.hpp>
#endif
#endif // BOOST_FIBERS_DETAIL_CONFIG_H

View File

@@ -0,0 +1,45 @@
// Copyright (C) 2012 Vicente J. Botet Escriba
//
// 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_DELETE_HPP
#define BOOST_FIBERS_DETAIL_DELETE_HPP
#include <boost/config.hpp>
/**
* BOOST_FIBERS_DELETE_COPY_CTOR deletes the copy constructor when the compiler supports it or
* makes it private.
*
* BOOST_FIBERS_DELETE_COPY_ASSIGN deletes the copy assignment when the compiler supports it or
* makes it private.
*/
#ifndef BOOST_NO_DELETED_FUNCTIONS
#define BOOST_FIBERS_DELETE_COPY_CTOR(CLASS) \
CLASS(CLASS const&) = delete; \
#define BOOST_FIBERS_DELETE_COPY_ASSIGN(CLASS) \
CLASS& operator=(CLASS const&) = delete;
#else // BOOST_NO_DELETED_FUNCTIONS
#define BOOST_FIBERS_DELETE_COPY_CTOR(CLASS) \
private: \
CLASS(CLASS&); \
public:
#define BOOST_FIBERS_DELETE_COPY_ASSIGN(CLASS) \
private: \
CLASS& operator=(CLASS&); \
public:
#endif // BOOST_NO_DELETED_FUNCTIONS
/**
* BOOST_FIBERS_NO_COPYABLE deletes the copy constructor and assignment when the compiler supports it or
* makes them private.
*/
#define BOOST_FIBERS_NO_COPYABLE(CLASS) \
BOOST_FIBERS_DELETE_COPY_CTOR(CLASS) \
BOOST_FIBERS_DELETE_COPY_ASSIGN(CLASS)
#endif // BOOST_FIBERS_DETAIL_DELETE_HPP

View File

@@ -0,0 +1,154 @@
// 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_FIBER_BASE_H
#define BOOST_FIBERS_DETAIL_FIBER_BASE_H
#include <cstddef>
#include <iostream>
#include <vector>
#include <boost/assert.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/cstdint.hpp>
#include <boost/exception_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
class BOOST_FIBERS_DECL fiber_base : private noncopyable
{
public:
typedef intrusive_ptr< fiber_base > ptr_t;
private:
template< typename X, typename Y, typename Z >
friend class fiber_object;
std::size_t use_count_;
context::fcontext_t caller_;
context::fcontext_t * callee_;
int flags_;
exception_ptr except_;
std::vector< ptr_t > joining_;
void notify_();
protected:
virtual void deallocate_object() = 0;
virtual void unwind_stack() = 0;
public:
class id
{
private:
friend class fiber_base;
fiber_base::ptr_t impl_;
explicit id( fiber_base::ptr_t const& impl) BOOST_NOEXCEPT :
impl_( impl)
{}
public:
id() BOOST_NOEXCEPT :
impl_()
{}
bool operator==( id const& other) const BOOST_NOEXCEPT
{ return impl_ == other.impl_; }
bool operator!=( id const& other) const BOOST_NOEXCEPT
{ return impl_ != other.impl_; }
bool operator<( id const& other) const BOOST_NOEXCEPT
{ return impl_ < other.impl_; }
bool operator>( id const& other) const BOOST_NOEXCEPT
{ return other.impl_ < impl_; }
bool operator<=( id const& other) const BOOST_NOEXCEPT
{ return ! ( * this > other); }
bool operator>=( id const& other) const BOOST_NOEXCEPT
{ return ! ( * this < other); }
template< typename charT, class traitsT >
friend std::basic_ostream< charT, traitsT > &
operator<<( std::basic_ostream< charT, traitsT > & os, id const& other)
{
if ( 0 != other.impl_)
return os << other.impl_;
else
return os << "{not-valid}";
}
operator bool() const BOOST_NOEXCEPT
{ return 0 != impl_; }
bool operator!() const BOOST_NOEXCEPT
{ return 0 == impl_; }
};
fiber_base( context::fcontext_t *, bool, bool);
virtual ~fiber_base() {}
id get_id() const BOOST_NOEXCEPT
{ return id( ptr_t( const_cast< fiber_base * >( this) ) ); }
void resume();
void suspend();
void terminate();
void join( ptr_t const&);
bool force_unwind() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_force_unwind); }
bool unwind_requested() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_unwind_stack); }
bool preserve_fpu() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_preserve_fpu); }
bool is_complete() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_complete); }
bool is_canceled() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_canceled); }
bool is_resumed() const BOOST_NOEXCEPT
{ return 0 != ( flags_ & flag_resumed); }
friend inline void intrusive_ptr_add_ref( fiber_base * p) BOOST_NOEXCEPT
{ ++p->use_count_; }
friend inline void intrusive_ptr_release( fiber_base * p)
{ if ( --p->use_count_ == 0) p->deallocate_object(); }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_FIBER_BASE_H

View File

@@ -0,0 +1,360 @@
// 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_FIBER_OBJECT_H
#define BOOST_FIBERS_DETAIL_FIBER_OBJECT_H
#include <cstddef>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/move/move.hpp>
#include <boost/ref.hpp>
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/flags.hpp>
#include <boost/fiber/flags.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
struct forced_unwind {};
template< typename Fiber >
void trampoline( intptr_t vp)
{
BOOST_ASSERT( vp);
Fiber * f( reinterpret_cast< Fiber * >( vp) );
f->exec();
}
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object : public fiber_base
{
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
reinterpret_cast< intptr_t >( this),
preserve_fpu() );
if ( except_) rethrow_exception( except_);
}
protected:
void unwind_stack() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_unwind_stack;
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
0, preserve_fpu() );
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
public:
#ifndef BOOST_NO_RVALUE_REFERENCES
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( forward< Fn >( fn) ),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#else
fiber_object( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
fiber_object( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
#endif
~fiber_object()
{ terminate(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object< reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base
{
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
reinterpret_cast< intptr_t >( this),
preserve_fpu() );
if ( except_) rethrow_exception( except_);
}
protected:
void unwind_stack() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_unwind_stack;
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
0, preserve_fpu() );
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
public:
fiber_object( reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~fiber_object()
{ terminate(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
template< typename Fn, typename StackAllocator, typename Allocator >
class fiber_object< const reference_wrapper< Fn >, StackAllocator, Allocator > : public fiber_base
{
public:
typedef typename Allocator::template rebind<
fiber_object<
Fn, StackAllocator, Allocator
>
>::other allocator_t;
private:
Fn fn_;
context::stack_t stack_;
StackAllocator stack_alloc_;
allocator_t alloc_;
static void destroy_( allocator_t & alloc, fiber_object * p)
{
alloc.destroy( p);
alloc.deallocate( p, 1);
}
fiber_object( fiber_object &);
fiber_object & operator=( fiber_object const&);
void enter_()
{
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
reinterpret_cast< intptr_t >( this),
preserve_fpu() );
if ( except_) rethrow_exception( except_);
}
protected:
void unwind_stack() BOOST_NOEXCEPT
{
BOOST_ASSERT( ! is_complete() );
flags_ |= flag_unwind_stack;
flags_ |= flag_resumed;
context::jump_fcontext(
& caller_, callee_,
0, preserve_fpu() );
flags_ &= ~flag_unwind_stack;
BOOST_ASSERT( is_complete() );
}
public:
fiber_object( const reference_wrapper< Fn > fn, attributes const& attr,
StackAllocator const& stack_alloc,
allocator_t const& alloc) :
fiber_base(
context::make_fcontext(
stack_alloc.allocate( attr.size), attr.size,
trampoline< fiber_object >),
stack_unwind == attr.do_unwind,
fpu_preserved == attr.preserve_fpu),
fn_( fn),
stack_( fiber_base::callee_->fc_stack),
stack_alloc_( stack_alloc),
alloc_( alloc)
{ enter_(); }
~fiber_object()
{ terminate(); }
void exec()
{
BOOST_ASSERT( ! is_complete() );
suspend();
try
{ fn_(); }
catch ( forced_unwind const&)
{}
catch (...)
{ except_ = current_exception(); }
flags_ &= ~flag_resumed;
flags_ |= flag_complete;
context::jump_fcontext( callee_, & caller_, 0, preserve_fpu() );
BOOST_ASSERT_MSG( false, "fiber is complete");
}
void deallocate_object()
{ destroy_( alloc_, this); }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_FIBER_OBJECT_H

View File

@@ -0,0 +1,38 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_DETAIL_FLAGS_H
#define BOOST_FIBERS_DETAIL_FLAGS_H
#include <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
enum flag_t
{
flag_force_unwind = 1 << 1,
flag_unwind_stack = 1 << 2,
flag_preserve_fpu = 1 << 3,
flag_complete = 1 << 4,
flag_resumed = 1 << 5,
flag_canceled = 1 << 6
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_FLAGS_H

View File

@@ -0,0 +1,90 @@
// (C) Copyright 2008-9 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)
#ifndef BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H
#define BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H
#include <algorithm>
#include <list>
#include <stdexcept>
#include <vector>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/mpl/if.hpp>
#include <boost/next_prior.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_fundamental.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
template<typename T>
struct future_traits
{
typedef boost::scoped_ptr<T> storage_type;
#ifdef BOOST_HAS_RVALUE_REFS
typedef T const& source_reference_type;
struct dummy;
typedef typename boost::mpl::if_<boost::is_fundamental<T>,dummy&,T&&>::type rvalue_source_type;
typedef typename boost::mpl::if_<boost::is_fundamental<T>,T,T&&>::type move_dest_type;
#else
typedef T& source_reference_type;
typedef typename boost::mpl::if_<boost::is_convertible<T&, BOOST_RV_REF( T) >, BOOST_RV_REF( T),T const&>::type rvalue_source_type;
typedef typename boost::mpl::if_<boost::is_convertible<T&,BOOST_RV_REF( T) >,BOOST_RV_REF( T),T>::type move_dest_type;
#endif
static void init(storage_type& storage,source_reference_type t)
{ storage.reset(new T(t)); }
static void init(storage_type& storage,rvalue_source_type t)
{ storage.reset(new T(static_cast<rvalue_source_type>(t))); }
static void cleanup(storage_type& storage)
{ storage.reset(); }
};
template<typename T>
struct future_traits<T&>
{
typedef T* storage_type;
typedef T& source_reference_type;
struct rvalue_source_type {};
typedef T& move_dest_type;
static void init(storage_type& storage,T& t)
{ storage=&t; }
static void cleanup(storage_type& storage)
{ storage=0; }
};
template<>
struct future_traits<void>
{
typedef bool storage_type;
typedef void move_dest_type;
static void init(storage_type& storage)
{ storage=true; }
static void cleanup(storage_type& storage)
{ storage=false; }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_FUTURE_TRAITS_H

View File

@@ -0,0 +1,87 @@
// 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_ID_H
#define BOOST_FIBERS_DETAIL_ID_H
#include <iostream>
#include <boost/config.hpp>
#include <boost/fiber/detail/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
class BOOST_FIBERS_DECL oid
{
private:
friend class fibers::auto_reset_event;
friend class fibers::condition;
friend class fibers::count_down_event;
friend class fibers::manual_reset_event;
friend class fibers::mutex;
friend class fibers::fibers;
intptr_t id_;
template< typename T >
oid( T * t) :
id_( t ? reinterpret_cast< intptr_t >( t) : 0)
{}
public:
oid() :
id_( 0)
{}
bool operator==( oid const& other) const
{ return id_ == other.id_; }
bool operator!=( oid const& other) const
{ return id_ != other.id_; }
bool operator<( oid const& other) const
{ return id_ < other.id_; }
bool operator>( oid const& other) const
{ return other.id_ < id_; }
bool operator<=( oid const& other) const
{ return !( other.id_ < id_); }
bool operator>=( oid 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, oid const& other)
{
if ( 0 != other.id_)
return os << "0x" << std::hex << other.id_;
else
return os << "{not-valid}";
}
operator bool() const
{ return 0 != id_; }
bool operator!() const
{ return 0 == id_; }
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_ID_H

View File

@@ -0,0 +1,35 @@
// 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_STRATIFIED_DETAIL_INTERRUPT_FLAGS_H
#define BOOST_STRATIFIED_DETAIL_INTERRUPT_FLAGS_H
#include <boost/config.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
enum interrupt_t_
{
INTERRUPTION_DISABLED = 1 << 0,
INTERRUPTION_ENABLED = 1 << 1,
INTERRUPTION_BLOCKED = 1 << 2
};
typedef char interrupt_type;
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_STRATIFIED_DETAIL_INTERRUPT_FLAGS_H

View File

@@ -0,0 +1,245 @@
// 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)
// (C) Copyright 2007-8 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba
#ifndef BOOST_FIBERS_MOVE_HPP
#define BOOST_FIBERS_MOVE_HPP
#include <boost/fiber/detail/config.hpp>
#ifndef BOOST_NO_SFINAE
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#endif
#include <boost/config/abi_prefix.hpp>
#include <boost/move/move.hpp>
#include <boost/fiber/detail/delete.hpp>
#define BOOST_NOEXCEPT
namespace boost {
namespace detail {
template <typename T>
struct has_move_emulation_enabled_aux_dummy_specialization;
template<typename T>
struct fibers_move_t
{
T& t;
explicit fibers_move_t(T& t_):
t(t_)
{}
T& operator*() const
{
return t;
}
T* operator->() const
{
return &t;
}
private:
void operator=(fibers_move_t&);
};
}
#ifndef BOOST_NO_SFINAE
template<typename T>
typename enable_if<boost::is_convertible<T&,boost::detail::fibers_move_t<T> >, boost::detail::fibers_move_t<T> >::type move(T& t)
{
return boost::detail::fibers_move_t<T>(t);
}
#endif
template<typename T>
boost::detail::fibers_move_t<T> move(boost::detail::fibers_move_t<T> t)
{
return t;
}
}
#if ! defined BOOST_NO_RVALUE_REFERENCES
#define BOOST_FIBERS_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_FIBERS_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_FIBERS_RV_REF_END BOOST_RV_REF_END
#define BOOST_FIBERS_RV(V) V
#define BOOST_FIBERS_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_FIBERS_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_FIBERS_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#elif ! defined BOOST_NO_RVALUE_REFERENCES && defined BOOST_MSVC
#define BOOST_FIBERS_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_FIBERS_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_FIBERS_RV_REF_END BOOST_RV_REF_END
#define BOOST_FIBERS_RV(V) V
#define BOOST_FIBERS_MAKE_RV_REF(RVALUE) RVALUE
#define BOOST_FIBERS_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_FIBERS_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#else
#if defined BOOST_FIBERS_USES_MOVE
#define BOOST_FIBERS_RV_REF(TYPE) BOOST_RV_REF(TYPE)
#define BOOST_FIBERS_RV_REF_BEG BOOST_RV_REF_BEG
#define BOOST_FIBERS_RV_REF_END BOOST_RV_REF_END
#define BOOST_FIBERS_RV(V) V
#define BOOST_FIBERS_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE_BEG(T) \
namespace detail { \
template <typename T> \
struct has_move_emulation_enabled_aux_dummy_specialization<
#define BOOST_FIBERS_DCL_MOVABLE_END > \
: integral_constant<bool, true> \
{}; \
}
#else
#define BOOST_FIBERS_RV_REF(TYPE) boost::detail::fibers_move_t< TYPE >
#define BOOST_FIBERS_RV_REF_BEG boost::detail::fibers_move_t<
#define BOOST_FIBERS_RV_REF_END >
#define BOOST_FIBERS_RV(V) (*V)
#define BOOST_FIBERS_FWD_REF(TYPE) BOOST_FWD_REF(TYPE)
#define BOOST_FIBERS_DCL_MOVABLE(TYPE) \
template <> \
struct has_move_emulation_enabled_aux< TYPE > \
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
{};
#define BOOST_FIBERS_DCL_MOVABLE_BEG(T) \
template <typename T> \
struct has_move_emulation_enabled_aux<
#define BOOST_FIBERS_DCL_MOVABLE_END > \
: BOOST_MOVE_BOOST_NS::integral_constant<bool, true> \
{};
#endif
namespace boost {
namespace detail {
template <typename T>
BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
make_rv_ref(T v) BOOST_NOEXCEPT
{
return (BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
}
// template <typename T>
// BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T &v) BOOST_NOEXCEPT
// {
// return (BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
// template <typename T>
// const BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type)
// make_rv_ref(T const&v) BOOST_NOEXCEPT
// {
// return (const BOOST_FIBERS_RV_REF(typename ::boost::remove_cv<typename ::boost::remove_reference<T>::type>::type))(v);
// }
}}
#define BOOST_FIBERS_MAKE_RV_REF(RVALUE) RVALUE.move()
//#define BOOST_FIBERS_MAKE_RV_REF(RVALUE) boost::detail::make_rv_ref(RVALUE)
#endif
#if ! defined BOOST_NO_RVALUE_REFERENCES
#define BOOST_FIBERS_MOVABLE(TYPE)
#else
#if defined BOOST_FIBERS_USES_MOVE
#define BOOST_FIBERS_MOVABLE(TYPE) \
::boost::rv<TYPE>& move() BOOST_NOEXCEPT \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
const ::boost::rv<TYPE>& move() const BOOST_NOEXCEPT \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
} \
operator ::boost::rv<TYPE>&() \
{ \
return *static_cast< ::boost::rv<TYPE>* >(this); \
} \
operator const ::boost::rv<TYPE>&() const \
{ \
return *static_cast<const ::boost::rv<TYPE>* >(this); \
}\
#else
#define BOOST_FIBERS_MOVABLE(TYPE) \
operator ::boost::detail::fibers_move_t<TYPE>() BOOST_NOEXCEPT \
{ \
return move(); \
} \
::boost::detail::fibers_move_t<TYPE> move() BOOST_NOEXCEPT \
{ \
::boost::detail::fibers_move_t<TYPE> x(*this); \
return x; \
} \
#endif
#endif
#define BOOST_FIBERS_MOVABLE_ONLY(TYPE) \
BOOST_FIBERS_NO_COPYABLE(TYPE) \
BOOST_FIBERS_MOVABLE(TYPE) \
#define BOOST_FIBERS_COPYABLE_AND_MOVABLE(TYPE) \
BOOST_FIBERS_MOVABLE(TYPE) \
#ifndef BOOST_NO_RVALUE_REFERENCES
namespace boost {
namespace fibers_detail {
template <class T>
typename decay<T>::type
decay_copy(T&& t)
{
return boost::forward<T>(t);
}
}}
#endif
#include <boost/config/abi_suffix.hpp>
#endif

View File

@@ -0,0 +1,124 @@
// 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_SCHEDULER_H
#define BOOST_FIBERS_DETAIL_SCHEDULER_H
#include <cstddef>
#include <deque>
#include <vector>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/function.hpp>
#include <boost/move/move.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/optional.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/fiber.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4251 4275)
# endif
namespace boost {
namespace fibers {
namespace detail {
class BOOST_FIBERS_DECL scheduler : private noncopyable
{
private:
struct schedulable
{
fiber_base::ptr_t f;
chrono::system_clock::time_point tp;
schedulable( fiber_base::ptr_t const& f_) :
f( f_), tp( (chrono::system_clock::time_point::max)() )
{ BOOST_ASSERT( f); }
schedulable(
fiber_base::ptr_t const& f_,
chrono::system_clock::time_point const& tp_) :
f( f_), tp( tp_)
{
BOOST_ASSERT( f);
BOOST_ASSERT( (chrono::system_clock::time_point::max)() != tp);
}
};
struct f_tag_t {};
struct tp_tag_t {};
typedef multi_index::multi_index_container<
schedulable,
multi_index::indexed_by<
multi_index::ordered_unique<
multi_index::tag< f_tag_t >,
multi_index::member< schedulable, fiber_base::ptr_t, & schedulable::f >
>,
multi_index::ordered_non_unique<
multi_index::tag< tp_tag_t >,
multi_index::member< schedulable, chrono::system_clock::time_point, & schedulable::tp >
>
>
> wqueue_t;
typedef wqueue_t::index< f_tag_t >::type f_idx_t;
typedef wqueue_t::index< tp_tag_t >::type tp_idx_t;
typedef std::deque< fiber_base::ptr_t > rqueue_t;
fiber_base::ptr_t active_fiber_;
rqueue_t rqueue_;
wqueue_t wqueue_;
f_idx_t & f_idx_;
tp_idx_t & tp_idx_;
scheduler();
public:
static scheduler & instance();
void spawn( fiber_base::ptr_t const&);
void join( fiber_base::ptr_t const&);
void cancel( fiber_base::ptr_t const&);
void notify( fiber_base::ptr_t const&);
fiber_base::ptr_t active() BOOST_NOEXCEPT
{ return active_fiber_; }
void sleep( chrono::system_clock::time_point const& abs_time);
bool run();
void wait();
void yield();
~scheduler();
};
}}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_DETAIL_SCHEDULER_H

View File

@@ -0,0 +1,165 @@
// 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_STACK_ALLOCATOR_H
#define BOOST_FIBERS_DETAIL_STACK_ALLOCATOR_H
#include <boost/config.hpp>
extern "C" {
#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
}
//#if _POSIX_C_SOURCE >= 200112L
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/context/fcontext.hpp>
#include <boost/context/detail/config.hpp>
#if !defined (SIGSTKSZ)
# define SIGSTKSZ (8 * 1024)
# define UDEF_SIGSTKSZ
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
inline
std::size_t pagesize()
{
// conform to POSIX.1-2001
static std::size_t size = ::sysconf( _SC_PAGESIZE);
return size;
}
inline
rlimit stacksize_limit_()
{
rlimit limit;
// conforming to POSIX.1-2001
const int result = ::getrlimit( RLIMIT_STACK, & limit);
BOOST_ASSERT( 0 == result);
return limit;
}
inline
rlimit stacksize_limit()
{
static rlimit limit = stacksize_limit_();
return limit;
}
inline
std::size_t page_count( std::size_t stacksize)
{
return static_cast< std::size_t >(
std::ceil(
static_cast< float >( stacksize) / pagesize() ) );
}
class stack_allocator
{
public:
static bool is_stack_unbound()
{ return RLIM_INFINITY == stacksize_limit().rlim_max; }
static std::size_t default_stacksize()
{
std::size_t size = 8 * minimum_stacksize();
if ( is_stack_unbound() ) return size;
BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
return maximum_stacksize() == size
? size
: std::min( size, maximum_stacksize() );
}
static std::size_t minimum_stacksize()
{ return SIGSTKSZ + sizeof( context::fcontext_t) + 15; }
static std::size_t maximum_stacksize()
{
BOOST_ASSERT( ! is_stack_unbound() );
return static_cast< std::size_t >( stacksize_limit().rlim_max);
}
void * allocate( std::size_t size) const
{
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages( page_count( size) + 1); // add one guard page
const std::size_t size_( pages * pagesize() );
BOOST_ASSERT( 0 < size && 0 < size_);
const int fd( ::open("/dev/zero", O_RDONLY) );
BOOST_ASSERT( -1 != fd);
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
void * limit =
# if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__)
::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
# else
::mmap( 0, size_, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
# endif
::close( fd);
if ( ! limit) throw std::bad_alloc();
std::memset( limit, size_, '\0');
// conforming to POSIX.1-2001
const int result( ::mprotect( limit, pagesize(), PROT_NONE) );
BOOST_ASSERT( 0 == result);
return static_cast< char * >( limit) + size_;
}
void deallocate( void * vp, std::size_t size) const
{
BOOST_ASSERT( vp);
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages = page_count( size) + 1;
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = static_cast< char * >( vp) - size_;
// conform to POSIX.4 (POSIX.1b-1993, _POSIX_C_SOURCE=199309L)
::munmap( limit, size_);
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#ifdef UDEF_SIGSTKSZ
# undef SIGSTKSZ
#endif
//#endif
#endif // BOOST_FIBERS_DETAIL_STACK_ALLOCATOR_H

View File

@@ -0,0 +1,160 @@
// 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_STACK_ALLOCATOR_H
#define BOOST_FIBERS_DETAIL_STACK_ALLOCATOR_H
#include <boost/config.hpp>
extern "C" {
#include <windows.h>
}
//#if defined (BOOST_WINDOWS) || _POSIX_C_SOURCE >= 200112L
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <boost/assert.hpp>
#include <boost/context/detail/config.hpp>
#include <boost/context/fcontext.hpp>
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4244 4267)
# endif
// x86_64
// test x86_64 before i386 because icc might
// define __i686__ for x86_64 too
#if defined(__x86_64__) || defined(__x86_64) \
|| defined(__amd64__) || defined(__amd64) \
|| defined(_M_X64) || defined(_M_AMD64)
// Windows seams not to provide a constant or function
// telling the minimal stacksize
# define MIN_STACKSIZE 8 * 1024
#else
# define MIN_STACKSIZE 4 * 1024
#endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
inline
SYSTEM_INFO system_info_()
{
SYSTEM_INFO si;
::GetSystemInfo( & si);
return si;
}
inline
SYSTEM_INFO system_info()
{
static SYSTEM_INFO si = system_info_();
return si;
}
inline
std::size_t pagesize()
{ return static_cast< std::size_t >( system_info().dwPageSize); }
inline
std::size_t page_count( std::size_t stacksize)
{
return static_cast< std::size_t >(
std::ceil(
static_cast< float >( stacksize) / pagesize() ) );
}
class stack_allocator
{
public:
// Windows seams not to provide a limit for the stacksize
static bool is_stack_unbound()
{ return true; }
static std::size_t default_stacksize()
{
using namespace std;
std::size_t size = 64 * 1024; // 64 kB
if ( is_stack_unbound() )
return max( size, minimum_stacksize() );
BOOST_ASSERT( maximum_stacksize() >= minimum_stacksize() );
return maximum_stacksize() == minimum_stacksize()
? minimum_stacksize()
: min( size, maximum_stacksize() );
}
// because Windows seams not to provide a limit for minimum stacksize
static std::size_t minimum_stacksize()
{ return MIN_STACKSIZE; }
// because Windows seams not to provide a limit for maximum stacksize
// maximum_stacksize() can never be called (pre-condition ! is_stack_unbound() )
static std::size_t maximum_stacksize()
{
BOOST_ASSERT( ! is_stack_unbound() );
return 1 * 1024 * 1024 * 1024; // 1GB
}
void * allocate( std::size_t size) const
{
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages( page_count( size) + 1); // add one guard page
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = ::VirtualAlloc( 0, size_, MEM_COMMIT, PAGE_READWRITE);
if ( ! limit) throw std::bad_alloc();
std::memset( limit, size_, '\0');
DWORD old_options;
const BOOL result = ::VirtualProtect(
limit, pagesize(), PAGE_READWRITE | PAGE_GUARD /*PAGE_NOACCESS*/, & old_options);
BOOST_ASSERT( FALSE != result);
return static_cast< char * >( limit) + size_;
}
void deallocate( void * vp, std::size_t size) const
{
BOOST_ASSERT( vp);
BOOST_ASSERT( minimum_stacksize() <= size);
BOOST_ASSERT( is_stack_unbound() || ( maximum_stacksize() >= size) );
const std::size_t pages = page_count( size) + 1;
const std::size_t size_ = pages * pagesize();
BOOST_ASSERT( 0 < size && 0 < size_);
void * limit = static_cast< char * >( vp) - size_;
::VirtualFree( limit, 0, MEM_RELEASE);
}
};
}}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
//#endif
#endif // BOOST_FIBERS_DETAIL_STACK_ALLOCATOR_H

View File

@@ -0,0 +1,81 @@
// 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_EXCEPTIONS_H
#define BOOST_fiber_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 fiber_canceled : public std::runtime_error
{
public:
fiber_canceled() :
std::runtime_error("fiber was canceled")
{}
};
class fiber_error : public std::runtime_error
{
public:
fiber_error( std::string const& msg) :
std::runtime_error( msg)
{}
};
class fiber_interrupted
{};
class fiber_moved : public std::logic_error
{
public:
fiber_moved() :
std::logic_error("fibers moved")
{}
};
class fiber_terminated : public std::runtime_error
{
public:
fiber_terminated() :
std::runtime_error("fiber terminated")
{}
};
class invalid_watermark : public std::runtime_error
{
public:
invalid_watermark() :
std::runtime_error("invalid watermark")
{}
};
class lock_error : public std::logic_error
{
public:
lock_error() :
std::logic_error("lock invalid")
{}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_fiber_EXCEPTIONS_H

View File

@@ -0,0 +1,360 @@
// 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_FIBER_H
#define BOOST_FIBERS_FIBER_H
#include <cstddef>
#include <memory>
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/type_traits/decay.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/fiber/attributes.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/detail/fiber_object.hpp>
#include <boost/fiber/stack_allocator.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 {
namespace detail {
class scheduler;
}
class fiber;
fiber migrate_from();
void migrate_to( BOOST_RV_REF( fiber) );
class BOOST_FIBERS_DECL fiber
{
private:
friend fiber migrate_from();
friend void migrate_to( BOOST_RV_REF( fiber) );
struct dummy
{ void nonnull() {} };
typedef detail::fiber_base base_t;
typedef base_t::ptr_t ptr_t;
typedef void ( dummy::*safe_bool)();
static void spawn_( ptr_t &);
ptr_t impl_;
BOOST_MOVABLE_BUT_NOT_COPYABLE( fiber);
fiber( ptr_t const& impl) BOOST_NOEXCEPT :
impl_( impl)
{ BOOST_ASSERT( impl_); }
public:
typedef detail::fiber_base::id id;
fiber() BOOST_NOEXCEPT :
impl_()
{}
#ifndef BOOST_NO_RVALUE_REFERENCES
#ifdef BOOST_MSVC
typedef void ( * fiber_fn)();
explicit fiber( fiber_fn fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
impl_()
{
typedef detail::fiber_object<
fiber_fn, stack_allocator, std::allocator< fiber >
> object_t;
object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename StackAllocator >
explicit fiber( fiber_fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >() ) :
impl_()
{
typedef detail::fiber_object<
fiber_fn, StackAllocator, std::allocator< fiber >
> object_t;
object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename StackAllocator, typename Allocator >
explicit fiber( fiber_fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc) :
impl_()
{
typedef detail::fiber_object<
fiber_fn, StackAllocator, Allocator
> object_t;
object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< fiber_fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
#endif
template< typename Fn >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc,
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( forward< Fn >( fn), attr, stack_alloc, a) );
spawn_( impl_);
}
#else
template< typename Fn >
explicit fiber( Fn fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_convertible< Fn &, BOOST_RV_REF( Fn) >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator >
explicit fiber( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_convertible< Fn &, BOOST_RV_REF( Fn) >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( Fn fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc,
typename disable_if<
is_convertible< Fn &, BOOST_RV_REF( Fn) >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr = attributes(),
stack_allocator const& stack_alloc = stack_allocator(),
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, stack_allocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
std::allocator< fiber > const& alloc = std::allocator< fiber >(),
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, std::allocator< fiber >
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
template< typename Fn, typename StackAllocator, typename Allocator >
explicit fiber( BOOST_RV_REF( Fn) fn, attributes const& attr,
StackAllocator const& stack_alloc,
Allocator const& alloc,
typename disable_if<
is_same< typename decay< Fn >::type, fiber >,
dummy *
>::type = 0) :
impl_()
{
typedef detail::fiber_object<
Fn, StackAllocator, Allocator
> object_t;
typename object_t::allocator_t a( alloc);
impl_ = ptr_t(
// placement new
::new( a.allocate( 1) ) object_t( fn, attr, stack_alloc, a) );
spawn_( impl_);
}
#endif
~fiber()
{ if ( impl_) join(); }
fiber( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT :
impl_()
{ swap( other); }
fiber & operator=( BOOST_RV_REF( fiber) other) BOOST_NOEXCEPT
{
fiber tmp( move( other) );
swap( tmp);
return * this;
}
operator safe_bool() const BOOST_NOEXCEPT
{ return ( ! empty() && ! impl_->is_complete() ) ? & dummy::nonnull : 0; }
bool operator!() const BOOST_NOEXCEPT
{ return empty() || impl_->is_complete(); }
void swap( fiber & other) BOOST_NOEXCEPT
{ impl_.swap( other.impl_); }
bool empty() const BOOST_NOEXCEPT
{ return ! impl_; }
id get_id() const BOOST_NOEXCEPT
{ return impl_ ? impl_->get_id() : id(); }
void cancel();
bool join();
};
inline
bool operator<( fiber const& l, fiber const& r)
{ return l.get_id() < r.get_id(); }
inline
void swap( fiber & l, fiber & r)
{ return l.swap( r); }
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_FIBER_H

View File

@@ -0,0 +1,27 @@
// Copyright Oliver Kowalke 2009.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_FIBERS_FLAGS_H
#define BOOST_FIBERS_FLAGS_H
namespace boost {
namespace fibers {
enum flag_unwind_t
{
stack_unwind = 0,
no_stack_unwind
};
enum flag_fpu_t
{
fpu_preserved = 0,
fpu_not_preserved
};
}}
#endif // BOOST_FIBERS_FLAGS_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,86 @@
// 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_THIS_STRATUM_INTERRUPTION_H
#define BOOST_THIS_STRATUM_INTERRUPTION_H
#include <cstddef>
#include <boost/config.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/interrupt_flags.hpp>
#include <boost/fiber/scheduler.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace this_fiber {
class restore_interruption;
class disable_interruption : private noncopyable
{
private:
friend class restore_interruption;
bool set_;
public:
disable_interruption() :
set_( ( fibers::scheduler::get_instance_()->active_fibers_->impl_->interrupt & fibers::detail::INTERRUPTION_BLOCKED) != 0)
{
if ( ! set_)
fibers::scheduler::get_instance_()->active_fibers_->impl_->interrupt |= fibers::detail::INTERRUPTION_BLOCKED;
}
~disable_interruption()
{
try
{
if ( ! set_)
fibers::scheduler::get_instance_()->active_fibers_->impl_->interrupt &= ~fibers::detail::INTERRUPTION_BLOCKED;
}
catch (...)
{}
}
};
class restore_interruption : private noncopyable
{
private:
disable_interruption & disabler_;
public:
explicit restore_interruption( disable_interruption & disabler) :
disabler_( disabler)
{
if ( ! disabler_.set_)
fibers::scheduler::get_instance_()->active_fibers_->impl_->interrupt &= ~fibers::detail::INTERRUPTION_BLOCKED;
}
~restore_interruption()
{
try
{
if ( ! disabler_.set_)
fibers::scheduler::get_instance_()->active_fibers_->impl_->interrupt |= fibers::detail::INTERRUPTION_BLOCKED;
}
catch (...)
{}
}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_THIS_STRATUM_INTERRUPTION_H

View File

@@ -0,0 +1,77 @@
// 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_MANUAL_RESET_EVENT_H
#define BOOST_FIBERS_MANUAL_RESET_EVENT_H
#include <cstddef>
#include <deque>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/mutex.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355 4251 4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL manual_reset_event : private noncopyable
{
private:
enum state
{
SET = 0,
RESET
};
state state_;
std::size_t waiters_;
mutex enter_mtx_;
std::deque<
detail::fiber_base::ptr_t
> waiting_;
public:
explicit manual_reset_event( bool = false);
void set();
void reset();
void wait();
template< typename TimeDuration >
bool timed_wait( TimeDuration const& dt)
{ return timed_wait( chrono::system_clock::now() + dt); }
bool timed_wait( chrono::system_clock::time_point const& abs_time);
bool try_wait();
};
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_MANUAL_RESET_EVENT_H

View File

@@ -0,0 +1,73 @@
// 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)
//
// based on boost::interprocess::sync::interprocess_spin_mutex
#ifndef BOOST_FIBERS_MUTEX_H
#define BOOST_FIBERS_MUTEX_H
#include <deque>
#include <boost/config.hpp>
#include <boost/thread/locks.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/detail/config.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4355 4251 4275)
# endif
namespace boost {
namespace fibers {
class BOOST_FIBERS_DECL mutex : private noncopyable
{
private:
enum state
{
LOCKED = 0,
UNLOCKED
};
state state_;
detail::fiber_base::id owner_;
std::deque<
detail::fiber_base::ptr_t
> waiting_;
bool checked_;
public:
typedef unique_lock< mutex > scoped_lock;
mutex( bool = true);
void lock();
bool try_lock();
void unlock();
};
typedef mutex try_mutex;
}}
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_MUTEX_H

View File

@@ -0,0 +1,145 @@
// 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_THIS_FIBER_OPERATIONS_H
#define BOOST_THIS_FIBER_OPERATIONS_H
#include <boost/assert.hpp>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/move/move.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/fiber/detail/scheduler.hpp>
#include <boost/fiber/detail/fiber_base.hpp>
#include <boost/fiber/fiber.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace this_fiber {
inline
bool is_fiberized()
{ return fibers::detail::scheduler::instance().active(); }
inline
fibers::fiber::id get_id()
{
BOOST_ASSERT( is_fiberized() );
return fibers::detail::scheduler::instance().active()->get_id();
}
inline
void sleep( chrono::system_clock::time_point const& abs_time)
{
BOOST_ASSERT( is_fiberized() );
fibers::detail::scheduler::instance().sleep( abs_time);
}
template< typename TimeDuration >
void sleep( TimeDuration const& dt)
{ sleep( chrono::system_clock::now() + dt); }
inline
void yield()
{
BOOST_ASSERT( is_fiberized() );
fibers::detail::scheduler::instance().yield();
}
inline
void yield_break()
{
BOOST_ASSERT( is_fiberized() );
throw fibers::detail::forced_unwind();
}
}
namespace fibers {
inline
bool run()
{ return detail::scheduler::instance().run(); }
#define BOOST_FIBERS_WAITFOR_FIBER_FN_ARG(z,n,unused) \
fiber & BOOST_PP_CAT(f,n)
#define BOOST_FIBERS_WAITFOR_FIBER_FN_ARGS(n) \
BOOST_PP_ENUM(n,BOOST_FIBERS_WAITFOR_FIBER_FN_ARG,~)
#define BOOST_FIBERS_WAITFOR_FIBER_AND(z,n,t) \
BOOST_PP_EXPR_IF(n,&&) BOOST_PP_CAT(f,n)
#define BOOST_FIBERS_WAITFOR_FIBER_OR(z,n,t) \
BOOST_PP_EXPR_IF(n,||) BOOST_PP_CAT(f,n)
#define BOOST_FIBERS_WAITFOR_FIBER_CANCEL(z,n,t) \
if ( BOOST_PP_CAT(f,n) ) BOOST_PP_CAT(f,n).cancel(); \
else i = BOOST_PP_INC(n);
#define BOOST_FIBERS_WAITFOR_FIBER_READY(z,n,t) \
if ( ! BOOST_PP_CAT(f,n) ) return BOOST_PP_INC(n);
#define BOOST_FIBERS_WAITFOR_FIBER_ALL(z,n,unused) \
inline \
void waitfor_all( BOOST_FIBERS_WAITFOR_FIBER_FN_ARGS(n) ) \
{ \
while ( BOOST_PP_REPEAT(n,BOOST_FIBERS_WAITFOR_FIBER_OR,~) ) \
run(); \
}
#define BOOST_FIBERS_WAITFOR_FIBER_ANY(z,n,unused) \
inline \
unsigned int waitfor_any( BOOST_FIBERS_WAITFOR_FIBER_FN_ARGS(n) ) \
{ \
while ( BOOST_PP_REPEAT(n,BOOST_FIBERS_WAITFOR_FIBER_AND,~) ) \
run(); \
BOOST_PP_REPEAT(n,BOOST_FIBERS_WAITFOR_FIBER_READY,~); \
return 0; \
}
#define BOOST_FIBERS_WAITFOR_FIBER_ANY_AND_CANCEL(z,n,unused) \
inline \
unsigned int waitfor_any_and_cancel( BOOST_FIBERS_WAITFOR_FIBER_FN_ARGS(n) ) \
{ \
while ( BOOST_PP_REPEAT(n,BOOST_FIBERS_WAITFOR_FIBER_AND,~) ) \
run(); \
unsigned int i = 0; \
BOOST_PP_REPEAT(n,BOOST_FIBERS_WAITFOR_FIBER_CANCEL,~); \
return i; \
}
#ifndef BOOST_FIBERS_WAITFOR_FIBER_MAX_ARITY
#define BOOST_FIBERS_WAITFOR_FIBER_MAX_ARITY 12
#endif
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_FIBERS_WAITFOR_FIBER_MAX_ARITY, BOOST_FIBERS_WAITFOR_FIBER_ALL, ~)
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_FIBERS_WAITFOR_FIBER_MAX_ARITY, BOOST_FIBERS_WAITFOR_FIBER_ANY, ~)
BOOST_PP_REPEAT_FROM_TO( 2, BOOST_FIBERS_WAITFOR_FIBER_MAX_ARITY, BOOST_FIBERS_WAITFOR_FIBER_ANY_AND_CANCEL, ~)
#undef BOOST_FIBERS_WAITFOR_FIBER_READY
#undef BOOST_FIBERS_WAITFOR_FIBER_ALL
#undef BOOST_FIBERS_WAITFOR_FIBER_ANY
#undef BOOST_FIBERS_WAITFOR_FIBER_ANY_AND_CANCEL
#undef BOOST_FIBERS_WAITFOR_FIBER_CANCEL
#undef BOOST_FIBERS_WAITFOR_FIBER_OR
#undef BOOST_FIBERS_WAITFOR_FIBER_AND
#undef BOOST_FIBERS_WAITFOR_FIBER_ARGS
#undef BOOST_FIBERS_WAITFOR_FIBER_ARG
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_THIS_FIBER_OPERATIONS_H

View File

@@ -0,0 +1,23 @@
// 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_STACK_ALLOCATOR_H
#define BOOST_FIBERS_STACK_ALLOCATOR_H
#include <boost/config.hpp>
#if defined (BOOST_WINDOWS)
#include <boost/fiber/detail/stack_allocator_windows.hpp>
#else
#include <boost/fiber/detail/stack_allocator_posix.hpp>
#endif
namespace boost {
namespace fibers {
using detail::stack_allocator;
}}
#endif // BOOST_FIBERS_STACK_ALLOCATOR_H

View File

@@ -0,0 +1,216 @@
// 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)
//
// idea of node-base locking from 'C++ Concurrency in Action', Anthony Williams
#ifndef BOOST_FIBERS_UNBOUNDED_CHANNEL_H
#define BOOST_FIBERS_UNBOUNDED_CHANNEL_H
#include <cstddef>
#include <stdexcept>
#include <boost/chrono/system_clocks.hpp>
#include <boost/config.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/optional.hpp>
#include <boost/utility.hpp>
#include <boost/fiber/exceptions.hpp>
#include <boost/fiber/condition.hpp>
#include <boost/fiber/mutex.hpp>
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
#endif
namespace boost {
namespace fibers {
namespace detail {
template< typename T >
struct unbounded_channel_node
{
typedef intrusive_ptr< unbounded_channel_node > ptr;
std::size_t use_count;
T va;
ptr next;
unbounded_channel_node() :
use_count( 0),
va(),
next()
{}
};
template< typename T >
void intrusive_ptr_add_ref( unbounded_channel_node< T > * p)
{ ++p->use_count; }
template< typename T >
void intrusive_ptr_release( unbounded_channel_node< T > * p)
{ if ( 0 == --p->use_count) delete p; }
}
template< typename T >
class unbounded_channel : private noncopyable
{
public:
typedef optional< T > value_type;
private:
typedef detail::unbounded_channel_node< value_type > node_type;
enum state
{
ACTIVE = 0,
DEACTIVE
};
state state_;
typename node_type::ptr head_;
mutable mutex head_mtx_;
typename node_type::ptr tail_;
mutable mutex tail_mtx_;
condition not_empty_cond_;
bool active_() const
{ return ACTIVE == state_; }
void deactivate_()
{ state_ = DEACTIVE; }
bool empty_() const
{ return head_ == get_tail_(); }
typename node_type::ptr get_tail_() const
{
mutex::scoped_lock lk( tail_mtx_);
typename node_type::ptr tmp = tail_;
return tmp;
}
typename node_type::ptr pop_head_()
{
typename node_type::ptr old_head = head_;
head_ = old_head->next;
return old_head;
}
public:
unbounded_channel() :
state_( ACTIVE),
head_( new node_type() ),
head_mtx_(),
tail_( head_),
tail_mtx_(),
not_empty_cond_()
{}
bool active() const
{ return active_(); }
void deactivate()
{
mutex::scoped_lock lk( head_mtx_);
deactivate_();
not_empty_cond_.notify_all();
}
bool empty() const
{
mutex::scoped_lock lk( head_mtx_);
return empty_();
}
void put( T const& t)
{
typename node_type::ptr new_node( new node_type() );
{
mutex::scoped_lock lk( tail_mtx_);
if ( ! active_() )
throw std::runtime_error("queue is not active");
tail_->va = t;
tail_->next = new_node;
tail_ = new_node;
}
not_empty_cond_.notify_one();
}
bool take( value_type & va)
{
mutex::scoped_lock lk( head_mtx_);
bool empty = empty_();
if ( ! active_() && empty)
return false;
if ( empty)
{
// try
// {
while ( active_() && empty_() )
not_empty_cond_.wait( lk);
// }
// catch ( fibers_interrupted const&)
// { return false; }
}
if ( ! active_() && empty_() )
return false;
swap( va, head_->va);
pop_head_();
return va;
}
template< typename TimeDuration >
bool take( value_type & va, TimeDuration const& dt)
{ return take( va, chrono::system_clock::now() + dt); }
bool take( value_type & va, chrono::system_clock::time_point const& abs_time)
{
mutex::scoped_lock lk( head_mtx_);
bool empty = empty_();
if ( ! active_() && empty)
return false;
if ( empty)
{
// try
// {
while ( active_() && empty_() )
{
if ( ! not_empty_cond_.timed_wait( lk, abs_time) )
return false;
}
// }
// catch ( fibers_interrupted const&)
// { return false; }
}
if ( ! active_() && empty_() )
return false;
swap( va, head_->va);
pop_head_();
return va;
}
bool try_take( value_type & va)
{
mutex::scoped_lock lk( head_mtx_);
if ( empty_() )
return false;
swap( va, head_->va);
pop_head_();
return va;
}
};
}}
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_SUFFIX
#endif
#endif // BOOST_FIBERS_UNBOUNDED_CHANNEL_H