From e43cf5b1ac20cd50ae51ac54ee87312344bce0bf Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Mon, 15 Feb 2016 19:49:22 +0100 Subject: [PATCH] enum for context types --- examples/Jamfile.v2 | 1 + examples/asio/round_robin.hpp | 4 +- examples/work_sharing.cpp | 10 +-- examples/work_stealing.cpp | 4 +- include/boost/fiber/context.hpp | 31 ++++----- include/boost/fiber/type.hpp | 108 ++++++++++++++++++++++++++++++++ src/context.cpp | 10 +-- src/scheduler.cpp | 20 +++--- 8 files changed, 143 insertions(+), 45 deletions(-) create mode 100644 include/boost/fiber/type.hpp diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2 index 57df9f9c..77f6913e 100644 --- a/examples/Jamfile.v2 +++ b/examples/Jamfile.v2 @@ -17,6 +17,7 @@ import toolset ; project boost/fiber/example : requirements ../build//boost_fiber + /boost/thread//boost_thread gcc,on:-fsplit-stack gcc,on:-DBOOST_USE_SEGMENTED_STACKS clang,on:-fsplit-stack diff --git a/examples/asio/round_robin.hpp b/examples/asio/round_robin.hpp index c98357d5..533d4185 100644 --- a/examples/asio/round_robin.hpp +++ b/examples/asio/round_robin.hpp @@ -86,7 +86,7 @@ public: BOOST_ASSERT( nullptr != ctx); BOOST_ASSERT( ! ctx->ready_is_linked() ); ctx->ready_link( ready_queue_); - if ( ! ctx->is_dispatcher_context() ) { + if ( ! ctx->is_context( boost::fibers::type::dispatcher_context) ) { ++counter_; } } @@ -98,7 +98,7 @@ public: ready_queue_.pop_front(); BOOST_ASSERT( nullptr != ctx); BOOST_ASSERT( ! ctx->ready_is_linked() ); - if ( ! ctx->is_dispatcher_context() ) { + if ( ! ctx->is_context( boost::fibers::type::dispatcher_context) ) { --counter_; } } diff --git a/examples/work_sharing.cpp b/examples/work_sharing.cpp index 1f3903be..c7bd6e0d 100644 --- a/examples/work_sharing.cpp +++ b/examples/work_sharing.cpp @@ -46,18 +46,12 @@ public: virtual void awakened( boost::fibers::context * ctx) noexcept { BOOST_ASSERT( nullptr != ctx); - if ( ctx->is_main_context() ) { /*< - recognize when we're passed this thread's main fiber + if ( ctx->is_context( boost::fibers::type::pinned_context) ) { /*< + recognize when we're passed this thread's main or dispatcher fiber never put this thread's main fiber on the queue stash it in separate slot >*/ local_queue_.push( ctx); - } else if ( ctx->is_dispatcher_context() ) { /*< - recognize when we're passed this thread's dispatcher fiber - never put this thread's main fiber on the queue - stash it in separate slot - >*/ - local_queue_.push( ctx); } else { lock_t lk(rqueue_mtx_); /*< worker fiber, enqueue on shared queue diff --git a/examples/work_stealing.cpp b/examples/work_stealing.cpp index 50dea6c6..1389732d 100644 --- a/examples/work_stealing.cpp +++ b/examples/work_stealing.cpp @@ -55,7 +55,7 @@ public: rqueue_t::iterator i = std::find_if( rqueue_.begin(), e, [](boost::fibers::context const& ctx){ // prevent migrating main- and dispatcher-fiber - return ! ctx.is_main_context() && ! ctx.is_dispatcher_context(); + return ! ctx.is_context( boost::fibers::type::pinned_context); }); if ( i != e) { ctx = & ( * i); @@ -82,7 +82,7 @@ public: rqueue_t::const_iterator e = rqueue_.end(); rqueue_t::const_iterator i = std::find_if( rqueue_.begin(), e, [](boost::fibers::context const& ctx){ - return ! ctx.is_main_context() && ! ctx.is_dispatcher_context(); + return ! ctx.is_context( boost::fibers::type::pinned_context); }); return i != e; } diff --git a/include/boost/fiber/context.hpp b/include/boost/fiber/context.hpp index 993f2603..921c26cd 100644 --- a/include/boost/fiber/context.hpp +++ b/include/boost/fiber/context.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef BOOST_HAS_ABI_HEADERS # include BOOST_ABI_PREFIX @@ -132,12 +133,9 @@ private: friend class scheduler; enum flag_t { - flag_main_context = 1 << 1, - flag_dispatcher_context = 1 << 2, - flag_worker_context = 1 << 3, - flag_terminated = 1 << 4, - flag_interruption_blocked = 1 << 5, - flag_interruption_requested = 1 << 6 + flag_terminated = 1 << 1, + flag_interruption_blocked = 1 << 2, + flag_interruption_requested = 1 << 3 }; struct BOOST_FIBERS_DECL fss_data { @@ -165,10 +163,12 @@ private: #if ! defined(BOOST_FIBERS_NO_ATOMICS) std::atomic< std::size_t > use_count_{ 0 }; - std::atomic< int > flags_; + std::atomic< unsigned int > flags_; + std::atomic< type > type_; #else std::size_t use_count_{ 0 }; - int flags_; + unsigned int flags_; + type type_; #endif scheduler * scheduler_{ nullptr }; #if (BOOST_EXECUTION_CONTEXT==1) @@ -316,7 +316,8 @@ public: boost::context::preallocated palloc, StackAlloc salloc, Fn && fn, Tpl && tpl) : use_count_{ 1 }, // fiber instance or scheduler owner - flags_{ flag_worker_context }, + flags_{ 0 }, + type_{ type::worker_context }, #if (BOOST_EXECUTION_CONTEXT==1) # if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) ctx_{ std::allocator_arg, palloc, salloc, @@ -389,16 +390,8 @@ public: void set_ready( context *) noexcept; - bool is_main_context() const noexcept { - return 0 != ( flags_ & flag_main_context); - } - - bool is_dispatcher_context() const noexcept { - return 0 != ( flags_ & flag_dispatcher_context); - } - - bool is_worker_context() const noexcept { - return 0 != ( flags_ & flag_worker_context); + bool is_context( type t) const noexcept { + return type::none != ( type_ & t); } bool is_terminated() const noexcept { diff --git a/include/boost/fiber/type.hpp b/include/boost/fiber/type.hpp new file mode 100644 index 00000000..93462658 --- /dev/null +++ b/include/boost/fiber/type.hpp @@ -0,0 +1,108 @@ + +// 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) + +#ifndef BOOST_FIBERS_TYPE_H +#define BOOST_FIBERS_TYPE_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_PREFIX +#endif + +namespace boost { +namespace fibers { + +enum class type { + none = 0, + main_context = 1 << 1, + dispatcher_context = 1 << 2, + worker_context = 1 << 3, + pinned_context = main_context | dispatcher_context +}; + +inline +constexpr type +operator&( type l, type r) { + return static_cast< type >( + static_cast< unsigned int >( l) & static_cast< unsigned int >( r) ); +} + +inline +constexpr type +operator|( type l, type r) { + return static_cast< type >( + static_cast< unsigned int >( l) | static_cast< unsigned int >( r) ); +} + +inline +constexpr type +operator^( type l, type r) { + return static_cast< type >( + static_cast< unsigned int >( l) ^ static_cast< unsigned int >( r) ); +} + +inline +constexpr type +operator~( type l) { + return static_cast< type >( ~static_cast< unsigned int >( l) ); +} + +inline +type & +operator&=( type & l, type r) { + l = l & r; + return l; +} + +inline +type & +operator|=( type & l, type r) { + l = l | r; + return l; +} + +inline +type & +operator^=( type & l, type r) { + l = l ^ r; + return l; +} + +}} + +#ifdef BOOST_HAS_ABI_HEADERS +# include BOOST_ABI_SUFFIX +#endif + +#endif // BOOST_FIBERS_TYPE_H diff --git a/src/context.cpp b/src/context.cpp index fde1d7ee..21a018a4 100644 --- a/src/context.cpp +++ b/src/context.cpp @@ -118,7 +118,7 @@ context_initializer::context_initializer() { context_initializer::~context_initializer() { if ( 0 == --counter) { context * main_ctx = context::active_; - BOOST_ASSERT( main_ctx->is_main_context() ); + BOOST_ASSERT( main_ctx->is_context( type::main_context) ); scheduler * sched = main_ctx->get_scheduler(); sched->~scheduler(); main_ctx->~context(); @@ -182,7 +182,8 @@ context::set_ready_( context * ctx) noexcept { // main fiber context context::context( main_context_t) noexcept : use_count_{ 1 }, // allocated on main- or thread-stack - flags_{ flag_main_context }, + flags_{ 0 }, + type_{ type::main_context }, #if (BOOST_EXECUTION_CONTEXT==1) ctx_{ boost::context::execution_context::current() } { #else @@ -193,7 +194,8 @@ context::context( main_context_t) noexcept : // dispatcher fiber context context::context( dispatcher_context_t, boost::context::preallocated const& palloc, default_stack const& salloc, scheduler * sched) : - flags_{ flag_dispatcher_context }, + flags_{ 0 }, + type_{ type::dispatcher_context }, #if (BOOST_EXECUTION_CONTEXT==1) ctx_{ std::allocator_arg, palloc, salloc, [this,sched](void * vp) noexcept { @@ -415,7 +417,7 @@ context::interruption_blocked( bool blck) noexcept { void context::request_interruption( bool req) noexcept { - BOOST_ASSERT( ! is_main_context() && ! is_dispatcher_context() ); + BOOST_ASSERT( ! is_context( type::main_context) && ! is_context( type::dispatcher_context) ); if ( req) { flags_ |= flag_interruption_requested; } else { diff --git a/src/scheduler.cpp b/src/scheduler.cpp index 364b6c87..9a1aa198 100644 --- a/src/scheduler.cpp +++ b/src/scheduler.cpp @@ -36,8 +36,8 @@ scheduler::release_terminated_() noexcept { for ( terminated_queue_t::iterator i( terminated_queue_.begin() ); i != e;) { context * ctx = & ( * i); - BOOST_ASSERT( ! ctx->is_main_context() ); - BOOST_ASSERT( ! ctx->is_dispatcher_context() ); + BOOST_ASSERT( ! ctx->is_context( type::main_context) ); + BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) ); //BOOST_ASSERT( ctx->worker_is_linked() ); BOOST_ASSERT( ctx->is_terminated() ); BOOST_ASSERT( ! ctx->ready_is_linked() ); @@ -78,7 +78,7 @@ scheduler::sleep2ready_() noexcept { sleep_queue_t::iterator e = sleep_queue_.end(); for ( sleep_queue_t::iterator i = sleep_queue_.begin(); i != e;) { context * ctx = & ( * i); - BOOST_ASSERT( ! ctx->is_dispatcher_context() ); + BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) ); //BOOST_ASSERT( main_ctx_ == ctx || ctx->worker_is_linked() ); BOOST_ASSERT( ! ctx->is_terminated() ); BOOST_ASSERT( ! ctx->ready_is_linked() ); @@ -169,8 +169,8 @@ scheduler::dispatch() noexcept { worker_queue_t::iterator e = worker_queue_.end(); for ( worker_queue_t::iterator i = worker_queue_.begin(); i != e;) { context * ctx = & ( worker_queue_.front() ); - BOOST_ASSERT( ! ctx->is_main_context() ); - BOOST_ASSERT( ! ctx->is_dispatcher_context() ); + BOOST_ASSERT( ! ctx->is_context( type::main_context) ); + BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) ); if ( ctx->is_terminated() ) { i = worker_queue_.erase( i); } else { @@ -203,7 +203,7 @@ scheduler::set_ready( context * ctx) noexcept { BOOST_ASSERT( nullptr != ctx); BOOST_ASSERT( ! ctx->is_terminated() ); // dispatcher-context will never be passed to set_ready() - BOOST_ASSERT( ! ctx->is_dispatcher_context() ); + BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) ); // we do not test for wait-queue because // context::wait_is_linked() is not synchronized // with other threads @@ -225,11 +225,11 @@ scheduler::set_ready( context * ctx) noexcept { void scheduler::set_remote_ready( context * ctx) noexcept { BOOST_ASSERT( nullptr != ctx); - BOOST_ASSERT( ! ctx->is_dispatcher_context() ); + BOOST_ASSERT( ! ctx->is_context( type::dispatcher_context) ); BOOST_ASSERT( this == ctx->get_scheduler() ); // another thread might signal the main-context // from this thread - //BOOST_ASSERT( ! ctx->is_main_context() ); + //BOOST_ASSERT( ! ctx->is_context( type::main_context) ); // context ctx might in wait-/ready-/sleep-queue // we do not test this in this function // scheduler::dispatcher() has to take care @@ -251,8 +251,8 @@ scheduler::set_terminated( context * active_ctx) noexcept { #endif 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->is_context( type::main_context) ); + BOOST_ASSERT( ! active_ctx->is_context( type::dispatcher_context) ); //BOOST_ASSERT( active_ctx->worker_is_linked() ); BOOST_ASSERT( active_ctx->is_terminated() ); BOOST_ASSERT( ! active_ctx->ready_is_linked() );