mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-02 08:52:07 +00:00
190 lines
3.9 KiB
C++
190 lines
3.9 KiB
C++
|
|
// Copyright Oliver Kowalke 2013.
|
|
// Distributed under the Boost Software License, Version 1.0.
|
|
// (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
#include "boost/fiber/detail/worker_fiber.hpp"
|
|
|
|
#include <exception>
|
|
|
|
#include <boost/exception_ptr.hpp>
|
|
#include <boost/foreach.hpp>
|
|
#include <boost/thread/locks.hpp>
|
|
|
|
#include "boost/fiber/detail/scheduler.hpp"
|
|
#include "boost/fiber/exceptions.hpp"
|
|
|
|
#ifdef BOOST_HAS_ABI_HEADERS
|
|
# include BOOST_ABI_PREFIX
|
|
#endif
|
|
|
|
namespace boost {
|
|
namespace fibers {
|
|
namespace detail {
|
|
|
|
void
|
|
worker_fiber::trampoline_( coro_t::yield_type & yield)
|
|
{
|
|
BOOST_ASSERT( yield);
|
|
BOOST_ASSERT( ! is_terminated() );
|
|
|
|
callee_ = & yield;
|
|
set_running();
|
|
suspend();
|
|
|
|
try
|
|
{
|
|
BOOST_ASSERT( is_running() );
|
|
run();
|
|
BOOST_ASSERT( is_running() );
|
|
}
|
|
catch ( coro::detail::forced_unwind const&)
|
|
{
|
|
set_terminated();
|
|
release();
|
|
throw;
|
|
}
|
|
catch ( fiber_interrupted const&)
|
|
{ except_ = current_exception(); }
|
|
catch (...)
|
|
{ std::terminate(); }
|
|
|
|
set_terminated();
|
|
release();
|
|
suspend();
|
|
|
|
BOOST_ASSERT_MSG( false, "fiber already terminated");
|
|
}
|
|
|
|
worker_fiber::worker_fiber( attributes const& attrs) :
|
|
fiber_base(),
|
|
fss_data_(),
|
|
nxt_(),
|
|
tp_( (clock_type::time_point::max)() ),
|
|
callee_( 0),
|
|
caller_(
|
|
boost::bind( & worker_fiber::trampoline_, this, _1),
|
|
attrs),
|
|
state_( READY),
|
|
flags_( 0),
|
|
priority_( 0),
|
|
except_(),
|
|
waiting_()
|
|
{}
|
|
|
|
worker_fiber::~worker_fiber()
|
|
{
|
|
BOOST_ASSERT( is_terminated() );
|
|
BOOST_ASSERT( waiting_.empty() );
|
|
}
|
|
|
|
void
|
|
worker_fiber::release()
|
|
{
|
|
BOOST_ASSERT( is_terminated() );
|
|
|
|
std::vector< ptr_t > waiting;
|
|
|
|
// get all waiting fibers
|
|
splk_.lock();
|
|
waiting.swap( waiting_);
|
|
splk_.unlock();
|
|
|
|
// notify all waiting fibers
|
|
BOOST_FOREACH( worker_fiber::ptr_t p, waiting)
|
|
{ p->set_ready(); }
|
|
|
|
// release all fiber-specific-pointers
|
|
BOOST_FOREACH( fss_data_t::value_type & data, fss_data_)
|
|
{ data.second.do_cleanup(); }
|
|
}
|
|
|
|
bool
|
|
worker_fiber::join( ptr_t const& p)
|
|
{
|
|
unique_lock< spinlock > lk( splk_);
|
|
if ( is_terminated() ) return false;
|
|
waiting_.push_back( p);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
worker_fiber::interruption_blocked( bool blck) BOOST_NOEXCEPT
|
|
{
|
|
if ( blck)
|
|
flags_ |= flag_interruption_blocked;
|
|
else
|
|
flags_ &= ~flag_interruption_blocked;
|
|
}
|
|
|
|
void
|
|
worker_fiber::request_interruption( bool req) BOOST_NOEXCEPT
|
|
{
|
|
if ( req)
|
|
flags_ |= flag_interruption_requested;
|
|
else
|
|
flags_ &= ~flag_interruption_requested;
|
|
}
|
|
|
|
void
|
|
worker_fiber::thread_affinity( bool req) BOOST_NOEXCEPT
|
|
{
|
|
if ( req)
|
|
flags_ |= flag_thread_affinity;
|
|
else
|
|
flags_ &= ~flag_thread_affinity;
|
|
}
|
|
|
|
void *
|
|
worker_fiber::get_fss_data( void const* vp) const
|
|
{
|
|
uintptr_t key( reinterpret_cast< uintptr_t >( vp) );
|
|
fss_data_t::const_iterator i( fss_data_.find( key) );
|
|
|
|
return fss_data_.end() != i ? i->second.vp : 0;
|
|
}
|
|
|
|
void
|
|
worker_fiber::set_fss_data(
|
|
void const* vp,
|
|
fss_cleanup_function::ptr_t const& cleanup_fn,
|
|
void * data, bool cleanup_existing)
|
|
{
|
|
BOOST_ASSERT( cleanup_fn);
|
|
|
|
uintptr_t key( reinterpret_cast< uintptr_t >( vp) );
|
|
fss_data_t::iterator i( fss_data_.find( key) );
|
|
|
|
if ( fss_data_.end() != i)
|
|
{
|
|
if( cleanup_existing) i->second.do_cleanup();
|
|
if ( data)
|
|
fss_data_.insert(
|
|
i,
|
|
std::make_pair(
|
|
key,
|
|
fss_data( data, cleanup_fn) ) );
|
|
else fss_data_.erase( i);
|
|
}
|
|
else
|
|
fss_data_.insert(
|
|
std::make_pair(
|
|
key,
|
|
fss_data( data, cleanup_fn) ) );
|
|
}
|
|
|
|
void
|
|
worker_fiber::rethrow() const
|
|
{
|
|
BOOST_ASSERT( has_exception() );
|
|
|
|
rethrow_exception( except_);
|
|
}
|
|
|
|
}}}
|
|
|
|
#ifdef BOOST_HAS_ABI_HEADERS
|
|
# include BOOST_ABI_SUFFIX
|
|
#endif
|