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:
23
include/boost/fiber/all.hpp
Normal file
23
include/boost/fiber/all.hpp
Normal 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
|
||||
85
include/boost/fiber/attributes.hpp
Normal file
85
include/boost/fiber/attributes.hpp
Normal 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
|
||||
71
include/boost/fiber/auto_reset_event.hpp
Normal file
71
include/boost/fiber/auto_reset_event.hpp
Normal 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
|
||||
56
include/boost/fiber/barrier.hpp
Normal file
56
include/boost/fiber/barrier.hpp
Normal 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
|
||||
328
include/boost/fiber/bounded_channel.hpp
Normal file
328
include/boost/fiber/bounded_channel.hpp
Normal 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
|
||||
230
include/boost/fiber/condition.hpp
Normal file
230
include/boost/fiber/condition.hpp
Normal 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
|
||||
71
include/boost/fiber/count_down_event.hpp
Normal file
71
include/boost/fiber/count_down_event.hpp
Normal 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
|
||||
42
include/boost/fiber/detail/config.hpp
Normal file
42
include/boost/fiber/detail/config.hpp
Normal 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
|
||||
45
include/boost/fiber/detail/delete.hpp
Normal file
45
include/boost/fiber/detail/delete.hpp
Normal 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
|
||||
154
include/boost/fiber/detail/fiber_base.hpp
Normal file
154
include/boost/fiber/detail/fiber_base.hpp
Normal 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
|
||||
360
include/boost/fiber/detail/fiber_object.hpp
Normal file
360
include/boost/fiber/detail/fiber_object.hpp
Normal 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
|
||||
38
include/boost/fiber/detail/flags.hpp
Normal file
38
include/boost/fiber/detail/flags.hpp
Normal 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
|
||||
90
include/boost/fiber/detail/future_traits.hpp
Normal file
90
include/boost/fiber/detail/future_traits.hpp
Normal 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
|
||||
87
include/boost/fiber/detail/id.hpp
Normal file
87
include/boost/fiber/detail/id.hpp
Normal 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
|
||||
35
include/boost/fiber/detail/interrupt_flags.hpp
Normal file
35
include/boost/fiber/detail/interrupt_flags.hpp
Normal 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
|
||||
245
include/boost/fiber/detail/move.hpp
Normal file
245
include/boost/fiber/detail/move.hpp
Normal 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
|
||||
124
include/boost/fiber/detail/scheduler.hpp
Normal file
124
include/boost/fiber/detail/scheduler.hpp
Normal 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
|
||||
165
include/boost/fiber/detail/stack_allocator_posix.hpp
Normal file
165
include/boost/fiber/detail/stack_allocator_posix.hpp
Normal 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
|
||||
160
include/boost/fiber/detail/stack_allocator_windows.hpp
Normal file
160
include/boost/fiber/detail/stack_allocator_windows.hpp
Normal 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
|
||||
81
include/boost/fiber/exceptions.hpp
Normal file
81
include/boost/fiber/exceptions.hpp
Normal 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
|
||||
360
include/boost/fiber/fiber.hpp
Normal file
360
include/boost/fiber/fiber.hpp
Normal 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
|
||||
27
include/boost/fiber/flags.hpp
Normal file
27
include/boost/fiber/flags.hpp
Normal 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
|
||||
1290
include/boost/fiber/future.hpp
Normal file
1290
include/boost/fiber/future.hpp
Normal file
File diff suppressed because it is too large
Load Diff
86
include/boost/fiber/interruption.hpp
Normal file
86
include/boost/fiber/interruption.hpp
Normal 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
|
||||
77
include/boost/fiber/manual_reset_event.hpp
Normal file
77
include/boost/fiber/manual_reset_event.hpp
Normal 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
|
||||
73
include/boost/fiber/mutex.hpp
Normal file
73
include/boost/fiber/mutex.hpp
Normal 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
|
||||
145
include/boost/fiber/operations.hpp
Normal file
145
include/boost/fiber/operations.hpp
Normal 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
|
||||
23
include/boost/fiber/stack_allocator.hpp
Normal file
23
include/boost/fiber/stack_allocator.hpp
Normal 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
|
||||
216
include/boost/fiber/unbounded_channel.hpp
Normal file
216
include/boost/fiber/unbounded_channel.hpp
Normal 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
|
||||
Reference in New Issue
Block a user