2
0
mirror of https://github.com/boostorg/fiber.git synced 2026-02-18 01:52:24 +00:00

context::terminate() as replacement for set_terminated_()/release()

This commit is contained in:
Oliver Kowalke
2015-10-17 15:10:28 +02:00
parent edd439233a
commit 559e498982
3 changed files with 46 additions and 59 deletions

View File

@@ -191,8 +191,6 @@ private:
detail::spinlock splk_;
fiber_properties * properties_;
void set_terminated_() noexcept;
public:
class id {
private:
@@ -281,6 +279,7 @@ public:
auto tpl( std::move( tpl_) );
// jump back after initialization
void * vp = ctx();
// execute returned functor
if ( nullptr != vp) {
std::function< void() > * func( static_cast< std::function< void() > * >( vp) );
( * func)();
@@ -294,12 +293,8 @@ public:
} catch ( ... ) {
std::terminate();
}
// mark fiber as terminated
set_terminated_();
// notify waiting (joining) fibers
release();
// switch to another fiber
suspend();
// terminate context
terminate();
BOOST_ASSERT_MSG( false, "fiber already terminated");
}),
ready_hook_(),
@@ -325,14 +320,14 @@ public:
std::function< void() > * resume( std::function< void() > *);
void suspend( std::function< void() > * = nullptr) noexcept;
void release() noexcept;
void suspend( std::function< void() > *) noexcept;
void join();
void yield() noexcept;
void terminate() noexcept;
bool wait_until( std::chrono::steady_clock::time_point const&,
std::function< void() > * = nullptr) noexcept;

View File

@@ -152,14 +152,6 @@ context::reset_active() noexcept {
active_ = nullptr;
}
void
context::set_terminated_() noexcept {
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( splk_);
flags_ |= flag_terminated;
scheduler_->set_terminated( this);
}
// main fiber context
context::context( main_context_t) :
use_count_( 1), // allocated on main- or thread-stack
@@ -238,30 +230,6 @@ context::suspend( std::function< void() > * func) noexcept {
scheduler_->re_schedule( this, func);
}
void
context::release() noexcept {
BOOST_ASSERT( is_terminated() );
wait_queue_t tmp;
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( splk_);
tmp.swap( wait_queue_);
lk.unlock();
// notify all waiting fibers
wait_queue_t::iterator e = tmp.end();
for ( wait_queue_t::iterator i = tmp.begin(); i != e;) {
context * ctx = & ( * i);
// remove fiber from wait-queue
i = tmp.erase( i);
// notify scheduler
scheduler_->set_ready( ctx);
}
// release fiber-specific-data
for ( fss_data_t::value_type & data : fss_data_) {
data.second.do_cleanup();
}
fss_data_.clear();
}
void
context::join() {
// get active context
@@ -296,6 +264,30 @@ context::yield() noexcept {
scheduler_->yield( active_ctx);
}
void
context::terminate() noexcept {
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( splk_);
// mark as terminated
flags_ |= flag_terminated;
// notify all waiting fibers
while ( ! wait_queue_.empty() ) {
context * ctx = & wait_queue_.front();
// remove fiber from wait-queue
wait_queue_.pop_front();
// notify scheduler
scheduler_->set_ready( ctx);
}
lk.unlock();
// release fiber-specific-data
for ( fss_data_t::value_type & data : fss_data_) {
data.second.do_cleanup();
}
fss_data_.clear();
// switch to another context
scheduler_->set_terminated( this);
}
bool
context::wait_until( std::chrono::steady_clock::time_point const& tp,
std::function< void() > * func) noexcept {

View File

@@ -88,15 +88,12 @@ scheduler::release_terminated_() {
void
scheduler::remote_ready2ready_() {
remote_ready_queue_t tmp;
// protect for concurrent access
std::unique_lock< detail::spinlock > lk( remote_ready_splk_);
remote_ready_queue_.swap( tmp);
lk.unlock();
// get context from remote ready-queue
while ( ! tmp.empty() ) {
context * ctx = & tmp.front();
tmp.pop_front();
while ( ! remote_ready_queue_.empty() ) {
context * ctx = & remote_ready_queue_.front();
remote_ready_queue_.pop_front();
// store context in local queues
set_ready( ctx);
}
@@ -275,19 +272,22 @@ scheduler::set_remote_ready( context * ctx) noexcept {
}
void
scheduler::set_terminated( context * ctx) noexcept {
BOOST_ASSERT( nullptr != ctx);
BOOST_ASSERT( ! ctx->is_main_context() );
BOOST_ASSERT( ! ctx->is_dispatcher_context() );
BOOST_ASSERT( ctx->worker_is_linked() );
BOOST_ASSERT( ctx->is_terminated() );
BOOST_ASSERT( ! ctx->ready_is_linked() );
BOOST_ASSERT( ! ctx->sleep_is_linked() );
BOOST_ASSERT( ! ctx->wait_is_linked() );
scheduler::set_terminated( context * active_ctx) noexcept {
BOOST_ASSERT( nullptr != active_ctx);
BOOST_ASSERT( context::active() == active_ctx);
BOOST_ASSERT( ! active_ctx->is_main_context() );
BOOST_ASSERT( ! active_ctx->is_dispatcher_context() );
BOOST_ASSERT( active_ctx->worker_is_linked() );
BOOST_ASSERT( active_ctx->is_terminated() );
BOOST_ASSERT( ! active_ctx->ready_is_linked() );
BOOST_ASSERT( ! active_ctx->sleep_is_linked() );
BOOST_ASSERT( ! active_ctx->wait_is_linked() );
// store the terminated fiber in the terminated-queue
// the dispatcher-context will call
// intrusive_ptr_release( ctx);
ctx->terminated_link( terminated_queue_);
active_ctx->terminated_link( terminated_queue_);
// resume another fiber
resume_( active_ctx, get_next_(), nullptr);
}
void