From 20d08d98cd12a50798ddee46b1c5c2b36f0883f8 Mon Sep 17 00:00:00 2001 From: Oliver Kowalke Date: Fri, 19 Jun 2015 21:39:34 +0200 Subject: [PATCH] enable atomics with BOOST_FIBERS_USE_ATOMCIS --- doc/fibers.xml | 798 +++++++++++------- doc/html/fiber/acknowledgements.html | 2 +- doc/html/fiber/custom.html | 6 +- doc/html/fiber/fiber_mgmt.html | 12 +- doc/html/fiber/fiber_mgmt/fiber.html | 77 +- doc/html/fiber/fiber_mgmt/this_fiber.html | 44 +- doc/html/fiber/fiber_mgmt/winfibers.html | 50 ++ doc/html/fiber/fls.html | 6 +- doc/html/fiber/overview.html | 5 +- doc/html/fiber/performance.html | 355 +++++++- doc/html/fiber/rational.html | 40 +- doc/html/fiber/scheduling.html | 122 ++- doc/html/fiber/synchronization/channels.html | 6 +- doc/html/fiber_HTML.manifest | 2 +- doc/html/index.html | 4 +- doc/performance.qbk | 56 +- include/boost/fiber/condition.hpp | 18 +- include/boost/fiber/fiber_context.hpp | 16 +- include/boost/fiber/fiber_manager.hpp | 4 +- include/boost/fiber/mutex.hpp | 4 +- include/boost/fiber/operations.hpp | 4 +- include/boost/fiber/recursive_mutex.hpp | 4 +- include/boost/fiber/recursive_timed_mutex.hpp | 4 +- include/boost/fiber/timed_mutex.hpp | 4 +- performance/fiber/Jamfile.v2 | 4 + src/condition.cpp | 6 +- src/fiber_context.cpp | 4 +- src/fiber_manager.cpp | 2 +- src/mutex.cpp | 14 +- src/recursive_mutex.cpp | 14 +- src/recursive_timed_mutex.cpp | 18 +- src/timed_mutex.cpp | 18 +- test/test_condition_mt.cpp | 2 +- test/test_futures_mt.cpp | 2 +- test/test_mutex_mt.cpp | 2 +- 35 files changed, 1165 insertions(+), 564 deletions(-) create mode 100644 doc/html/fiber/fiber_mgmt/winfibers.html diff --git a/doc/fibers.xml b/doc/fibers.xml index ada9133d..7d3d9641 100644 --- a/doc/fibers.xml +++ b/doc/fibers.xml @@ -1,6 +1,6 @@ - @@ -139,10 +139,8 @@ - Boost.Fiber depends upon Boost.Chrono, - Boost.Context and Boost.Move. Boost version 1.55.0 - or greater is required. + Boost.Fiber depends upon Boost.Context. + Boost version 1.58.0 or greater is required. [info This library is C++14-only!] @@ -163,6 +161,8 @@ void swap( fiber & l, fiber & r) noexcept; struct sched_algorithm; +template< typename PROPS > +struct sched_algorithm_with_properties; class round_robin; void set_scheduling_algorithm( sched_algorithm * al) @@ -176,8 +176,8 @@ void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration); -bool thread_affinity() noexcept; -void thread_affinity( bool) noexcept; +template< typename PROPS > +PROPS & properties(); void interruption_point(); bool interruption_requested() noexcept; @@ -228,9 +228,8 @@ // this leads to undefined behaviour - Control is immediately transferred to the spawned fiber at construction. - When the constructor returns, the fiber might be complete or might - have suspended. + The spawned fiber is enqueued in the list of ready-to-run fibers + at construction. Exceptions @@ -428,7 +427,7 @@ by calling the fiber::get_id() fiber & operator=( fiber && other) noexcept; - operator bool() const noexcept; + explicit operator bool() const noexcept; bool operator!() const noexcept; @@ -438,15 +437,14 @@ by calling the fiber::get_id() id get_id() const noexcept; - bool thread_affinity() const noexcept; - - void thread_affinity( bool) noexcept; - void detach() noexcept; void join(); void interrupt() noexcept; + + template< typename PROPS > + PROPS & properties(); }; bool operator<( fiber const& l, fiber const& r) noexcept; @@ -904,14 +902,20 @@ by calling the fiber::get_id() - + + < TODO > + - Member - function thread_affinity( bool) + Member + function template< + typename PROPS + > PROPS + & properties() -void thread_affinity( bool) noexcept; +template< typename PROPS > +PROPS & properties(); @@ -927,86 +931,16 @@ by calling the fiber::get_id() Effects: - - Set thread affinity for the fiber referenced by *this. - Throws: - - Nothing - Note: - - "Thread affinity" is only meaningful for certain scheduler - algorithms, such as round_robin_ws. Many schedulers - ignore this fiber attribute. With a scheduler that might potentially - migrate a fiber from its initial thread to another, the value true prevents migration: the fiber will - always run on its current thread. The default is false: - normally, with an applicable scheduler, a fiber is allowed to migrate - across threads. - - - - - See also: - - - this_fiber::thread_affinity() - - - - - - Member - function thread_affinity() - -bool thread_affinity() const noexcept; - - - - - Preconditions: - - - *this - refers to a fiber of execution. - - - - - Returns: - - - thread affinity for the fiber referenced by *this. - - - - - Throws: - - - Nothing - - - - - See also: - - - this_fiber::thread_affinity() - @@ -1017,7 +951,7 @@ by calling the fiber::get_id() function operator bool() -operator bool() const noexcept; +explicit operator bool() const noexcept; @@ -1504,8 +1438,8 @@ by calling the fiber::get_id() void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration); -bool thread_affinity() noexcept; -void thread_affinity( bool req) noexcept; +template< typename PROPS > +PROPS & properties(); void interruption_point(); bool interruption_requested() noexcept; @@ -1684,43 +1618,35 @@ by calling the fiber::get_id() - - - Non-member - function this_fiber::thread_affinity() + < TODO > + + + + + Non-member + function this_fiber::properties() #include <boost/fiber/operations.hpp> -bool thread_affinity() noexcept; -void thread_affinity( bool req) noexcept; +template< typename PROPS > +PROPS & properties(); Effects: - - Set or report fiber::thread_affinity() for the - currently running fiber. - Throws: - - Nothing. - Note: - - fiber::thread_affinity() is false - by default. - @@ -1732,10 +1658,9 @@ by calling the fiber::get_id() #include <boost/fiber/interruption.hpp> + +void interruption_point(); - - void interruption_point(); - @@ -2044,6 +1969,16 @@ by calling the fiber::get_id() } +
+ <link linkend="fiber.fiber_mgmt.winfibers">Using WinFiber-API</link> + + Because the TIB (thread information block) is not fully described in the + MSDN, it might be possible that not all required TIB-parts are swapped. With + compiler flag BOOST_USE_WINFIBERS + fiber uses internally the + Windows Fiber API. + +
<link linkend="fiber.scheduling">Scheduling</link> @@ -2131,6 +2066,108 @@ by calling the fiber::get_id() virtual void priority( fiber_context *, int) noexcept = 0; + + + + + Effects: + + + Resets the priority of fiber f. + + + + + + To prevent the library from heap-allocating a default scheduler for a given + thread, that thread must call set_scheduling_algorithm() before + any other Boost.Fiber entry point. + +void thread_fn() +{ + my_fiber_scheduler mfs; + boost::fibers::set_scheduling_algorithm( & mfs); + ... +} + + + A fiber-scheduler must implement interface sched_algorithm. + Boost.Fiber provides one scheduler: round_robin. + + + You are explicitly permitted to code your own sched_algorithm subclass, + and to pass it to set_scheduling_algorithm(). + + + + + Class + sched_algorithm + + +#include <boost/fiber/algorithm.hpp> + +struct sched_algorithm +{ + virtual ~sched_algorithm() {} + + virtual void awakened( detail::worker_fiber *) = 0; + + virtual detail::worker_fiber * pick_next() = 0; + + virtual void priority( detail::worker_fiber *, int) noexcept = 0; +}; + + + + + Member + function awakened() + + +virtual void awakened( detail::worker_fiber * f) = 0; + + + + + Effects: + + + Marks fiber f, to be + ready to run. + + + + + + + + Member + function pick_next() + + +virtual detail::worker_fiber * pick_next() = 0; + + + + + Effects: + + + Depending on the scheduling algorithm, this function returns the fiber + which is to be resumed next. + + + + + + + + Member + function priority() + + +virtual void priority( detail::worker_fiber *, int) noexcept = 0; @@ -2159,6 +2196,13 @@ by calling the fiber::get_id() [info The example section provides a scheduler used for migrating fibers (work-stealing) between threads (different schedulers).] + + < TODO > + + + customized + scheduler +
<link linkend="fiber.stack">Stack allocation</link> @@ -3452,8 +3496,7 @@ by calling the fiber::get_id() bool is_empty(); - void push( value_type const& va); - void push( value_type && va); + channel_op_status push( value_type && va); channel_op_status pop( value_type & va); value_type value_pop(); @@ -3595,8 +3638,7 @@ by calling the fiber::get_id() function push() -void push( value_type const& va); -void push( value_type && va); +channel_op_status push( value_type && va); @@ -6914,133 +6956,6 @@ are
-
- <link linkend="fiber.asio">Example: asynchronous network I/O (boost.asio)</link> - - In the past, code using asio's asynchronous operations - was scattered by callbacks. Boost.Asio - provides with its new asynchronous result feature a new - way to simplify the code and make it easier to read. boost::asio::yield_context - internally uses __boost_coroutine__: - -void echo(boost::asio::ip::tcp::socket& socket,boost::asio::yield_context yield){ - char data[128]; - // read asynchronous data from socket - // execution context will be suspended until - // some bytes are read from socket - std::size_t n=socket.async_read_some(boost::asio::buffer(data),yield); - // write some bytes asynchronously - boost::asio::async_write(socket,boost::asio::buffer(data,n),yield); -} - - - Unfortunately __boost_coroutine__ (boost::asio::yield_context) - does not provide primitives to synchronize different coroutines (execution - contexts). - - - Boost.Fiber provides an example how fibers could be integrated into Boost.Asio - so that asynchronous operations from Boost.Asio - can be used together with fibers, synchronized by primitives provided by Boost.Fiber. - - - The example section contains a complete publish-subscribe application demonstrating - the use of fibers with asio's asynchronous operations. - boost::fibers::asio::yield_context abstracts the fiber - in asio's context. - -void subscriber::run( boost::fibers::asio::yield_fiber yield) -{ - boost::system::error_code ec; - - // read first message == channel name - std::string channel; - boost::asio::async_read( - socket_, - boost::asio::buffer( channel), - yield[ec]); - if ( ec) throw std::runtime_error("no channel from subscriber"); - - // register new channel - reg_.subscribe( channel, shared_from_this() ); - - for (;;) - { - boost::fibers::mutex::scoped_lock lk( mtx_); - // wait for published messages - // fiber gets suspended and will be woken up if a - // new message has to be published to subscriber - cond_.wait( lk); - - // '<fini>' terminates subscriber - // data_ is a private member of subscriber and - // gets filled by the publisher - // notification of available data via condition_var cond_ - if ( "<fini>" == std::string( data_) ) break; - - // write message asynchronously to subscriber - // fiber gets suspended until message was written - boost::asio::async_write( - socket_, - boost::asio::buffer( data_, max_length), - yield[ec]); - if ( ec) throw std::runtime_error("publishing message failed"); - } -} - - - C10K - problem - - - The C10K-website - - 'The C10K problem', Dan Kegel - - from Dan Kegel describes the problem of handling ten thousand clients - simultaneously and which strategies are possible. - - - Boost.Fiber and Boost.Asio - support the strategy 'serve many clients with each server thread, and use asynchronous - I/O' without scattering the logic across many callbacks (as was asio's previous - strategy) and overloading the operating system with too many threads. (Beyond - a certain number of threads, the overhead of the kernel scheduler starts to - swamp the available cores.) - - - Because Boost.Fiber contains synchronization - primitives, it is easy to synchronize different fibers and use asynchronous - network I/O at the same time. - - - Boost.Fiber provides the same classes and - interfaces as Boost.Thread. - Therefore developers are able to use patterns familiar from multi-threaded - programming. For instance the strategy 'serve one client with one thread' could - be transformed into 'serve one client with one fiber'. - - - Integration - - - The code for integrating boost.fiber int boost.asio can be found in the example - directory. THe author believes, that a better, more tight integration is possible - but requires input of boost.asio's author and maybe some changes in the boost.asio - framework. - - - The current integration pattern requires to runn boost::asio::io_service in boost::fibers::asio::run_service() - (separate fiber). - -
<link linkend="fiber.performance">Performance</link> @@ -7090,7 +7005,7 @@ are - 3 µs + 955 ns @@ -7128,12 +7043,12 @@ are - 16 µs + 20 µs - 3 µs + 3.2 µs @@ -7161,12 +7076,12 @@ are - 32 µs + 38 µs - 3 µs + 1.1 µs @@ -7199,7 +7114,7 @@ are - 4 µs + 2.4 µs @@ -7237,12 +7152,12 @@ are - 32.90 µs + 50.65 µs - 3.769 µs + 3.76 µs @@ -7254,12 +7169,12 @@ are - 32.71 µs + 52.99 µs - 2.789 µs + 2.78 µs @@ -7271,12 +7186,12 @@ are - 39.84 µs + 50.44 µs - 2.450 µs + 2.45 µs @@ -7288,12 +7203,12 @@ are - 49.78 µs + 45.19 µs - 2.919 µs + 2.91 µs @@ -7305,12 +7220,12 @@ are - 55.95 µs + 42.59 µs - 3.607 µs + 3.60 µs @@ -7322,12 +7237,12 @@ are - 42.88 µs + 42.30 µs - 4.579 µs + 4.57 µs @@ -7339,12 +7254,312 @@ are - 47.13 µs + 41.07 µs - 4.219 µs + 4.21 µs + + + + + + + + Using internally atomics by applying BOOST_FIBER_USE_ATOMICS. + + + Overhead of creating and joining + + + + + + thread + + + + + fiber + + + + + tbb + + + + + qthread + + + + + + + + + 31 µs + + + + + 1.1 µs + + + + + 570 ns + + + + + 620 ns + + + + + +
+ + Overhead of detach + + + + + + thread + + + + + fiber + + + + + + + + + 20 µs + + + + + 3.2 µs + + + + + +
+ + Overhead of yield + + + + + + thread + + + + + fiber + + + + + + + + + 38 µs + + + + + 1.3 µs + + + + + +
+ + Overhead of waiting on a future + + + + + + thread + + + + + fiber + + + + + + + + + 32 µs + + + + + 3.0 µs + + + + + +
+ + Scaling of creating and joining + + + + + + average of + + + + + thread + + + + + fiber + + + + + + + + + 10 + + + + + 50.65 µs + + + + + 4.83 µs + + + + + + + 50 + + + + + 52.99 µs + + + + + 4.84 µs + + + + + + + 100 + + + + + 50.44 µs + + + + + 5.24 µs + + + + + + + 500 + + + + + 45.19 µs + + + + + 4.86 µs + + + + + + + 1000 + + + + + 42.59 µs + + + + + 5.04 µs + + + + + + + 5000 + + + + + 42.30 µs + + + + + 5.07 µs + + + + + + + 10000 + + + + + 41.07 µs + + + + + 5.12 µs @@ -7390,18 +7605,6 @@ are sections. - fiber_managerwith free-functions - - - Some compiler store the this-pointer - on the stack so that the fiber, which has been migrated to another scheduler - (thread), access the invalid instance if it will be resumed from fiber_manager::run(). - - synchronization between fibers running in different threads @@ -7416,39 +7619,6 @@ are in different schedulers (different threads) or running int the same scheduler (same thread). - - migrating - fibers between threads - - - Fibers can be migrated between different schedulers, e.g. threads. The library - contains an example demonstrating how a scheduler could be implemented to allow - the migration of fibers. The example allows to move fibers from the ready-queue - (fibers with state READY, e.g. ready to be executed) of scheduler X to the ready-queue of scheduler Y. It is important that this operation is - thread-safe. If the fiber is put to the ready-queue of scheduler Y it might be selected for resumtion in the - next step, e.g. the fiber will be executed in the context of the thread running - scheudler Y. - - - variadric - template args for async()/packaged_task<> - - - Variadric template args for asnyc() implies variadic args support for packaged_task<>. - Because C++03 does not provide variadric template args the author desided not - to support this featrure for asnyc() and packaged_task<> otherwise the template signature would - be look different btween C++03 and C++11. In further versions of this library - variadric template args will be supported for C++03 with the usage of pre-processor - macros and template specialization. -
<link linkend="fiber.custom">Customization</link> @@ -7463,8 +7633,7 @@ are set_scheduling_algorithm() before any other Boost.Fiber entry point. -void thread_fn() -{ +void thread_fn() { my_fiber_scheduler mfs; boost::fibers::set_scheduling_algorithm( & mfs); ... @@ -7556,11 +7725,14 @@ are + + < TODO > +
<link linkend="fiber.acknowledgements">Acknowledgments</link> - I'd like to thank Eugene Yakubovich and Nat Goodspeed. + I'd like to thank Eugene Yakubovich and especially Nat Goodspeed.
diff --git a/doc/html/fiber/acknowledgements.html b/doc/html/fiber/acknowledgements.html index 71186ad3..c2ade5a3 100644 --- a/doc/html/fiber/acknowledgements.html +++ b/doc/html/fiber/acknowledgements.html @@ -26,7 +26,7 @@ Acknowledgments

- I'd like to thank Eugene Yakubovich and Nat Goodspeed. + I'd like to thank Eugene Yakubovich and especially Nat Goodspeed.

diff --git a/doc/html/fiber/custom.html b/doc/html/fiber/custom.html index ed22e182..c5d09c3b 100644 --- a/doc/html/fiber/custom.html +++ b/doc/html/fiber/custom.html @@ -36,8 +36,7 @@ In order to use a custom scheduler for a given thread, that thread must call set_scheduling_algorithm() before any other Boost.Fiber entry point.

-
void thread_fn()
-{
+
void thread_fn() {
     my_fiber_scheduler mfs;
     boost::fibers::set_scheduling_algorithm( & mfs);
     ...
@@ -135,6 +134,9 @@
           

+

+ < TODO > +

diff --git a/doc/html/fiber/fiber_mgmt.html b/doc/html/fiber/fiber_mgmt.html index a6a57f54..850356a9 100644 --- a/doc/html/fiber/fiber_mgmt.html +++ b/doc/html/fiber/fiber_mgmt.html @@ -31,6 +31,7 @@ fiber
Class fiber::id
Namespace this_fiber
+
Using WinFiber-API

@@ -46,6 +47,8 @@ void swap( fiber & l, fiber & r) noexcept; struct sched_algorithm; +template< typename PROPS > +struct sched_algorithm_with_properties; class round_robin; void set_scheduling_algorithm( sched_algorithm * al) @@ -59,8 +62,8 @@ void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration); -bool thread_affinity() noexcept; -void thread_affinity( bool) noexcept; +template< typename PROPS > +PROPS & properties(); void interruption_point(); bool interruption_requested() noexcept; @@ -113,9 +116,8 @@ // this leads to undefined behaviour

- Control is immediately transferred to the spawned fiber at construction. - When the constructor returns, the fiber might be complete or might - have suspended. + The spawned fiber is enqueued in the list of ready-to-run fibers + at construction.

diff --git a/doc/html/fiber/fiber_mgmt/fiber.html b/doc/html/fiber/fiber_mgmt/fiber.html index 1f19e43d..732079dc 100644 --- a/doc/html/fiber/fiber_mgmt/fiber.html +++ b/doc/html/fiber/fiber_mgmt/fiber.html @@ -51,7 +51,7 @@ fiber & operator=( fiber && other) noexcept; - operator bool() const noexcept; + explicit operator bool() const noexcept; bool operator!() const noexcept; @@ -61,15 +61,14 @@ id get_id() const noexcept; - bool thread_affinity() const noexcept; - - void thread_affinity( bool) noexcept; - void detach() noexcept; void join(); void interrupt() noexcept; + + template< typename PROPS > + PROPS & properties(); }; bool operator<( fiber const& l, fiber const& r) noexcept; @@ -400,12 +399,19 @@

-

+

+ < TODO > +

+
- Member - function thread_affinity( bool) + Member + function template< + typename PROPS + > PROPS + & properties()
-
void thread_affinity( bool) noexcept;
+
template< typename PROPS >
+PROPS & properties();
 

@@ -416,56 +422,11 @@ refers to a fiber of execution.

Effects:
-

- Set thread affinity for the fiber referenced by *this. -

+
Throws:
-

- Nothing -

+
Note:
-

- "Thread affinity" is only meaningful for certain scheduler - algorithms, such as round_robin_ws. Many schedulers - ignore this fiber attribute. With a scheduler that might potentially - migrate a fiber from its initial thread to another, the value true prevents migration: the fiber will - always run on its current thread. The default is false: - normally, with an applicable scheduler, a fiber is allowed to migrate - across threads. -

-
See also:
-

- this_fiber::thread_affinity() -

- -
-
- - Member - function thread_affinity() -
-
bool thread_affinity() const noexcept;
-
-
-

-
-
Preconditions:
-

- *this - refers to a fiber of execution. -

-
Returns:
-

- thread affinity for the fiber referenced by *this. -

-
Throws:
-

- Nothing -

-
See also:
-

- this_fiber::thread_affinity() -

+

@@ -478,7 +439,7 @@

-
operator bool() const noexcept;
+
explicit operator bool() const noexcept;
 

diff --git a/doc/html/fiber/fiber_mgmt/this_fiber.html b/doc/html/fiber/fiber_mgmt/this_fiber.html index bebfb1d6..77105fcc 100644 --- a/doc/html/fiber/fiber_mgmt/this_fiber.html +++ b/doc/html/fiber/fiber_mgmt/this_fiber.html @@ -7,7 +7,7 @@ - +
@@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -35,8 +35,8 @@ void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time) template< typename Rep, typename Period > void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration); -bool thread_affinity() noexcept; -void thread_affinity( bool req) noexcept; +template< typename PROPS > +PROPS & properties(); void interruption_point(); bool interruption_requested() noexcept; @@ -183,38 +183,33 @@

+

+ < TODO > +

- - - Non-member - function this_fiber::thread_affinity() + + + Non-member + function this_fiber::properties()

#include <boost/fiber/operations.hpp>
 
-bool thread_affinity() noexcept;
-void thread_affinity( bool req) noexcept;
+template< typename PROPS >
+PROPS & properties();
 

Effects:
-

- Set or report fiber::thread_affinity() for the - currently running fiber. -

+
Throws:
-

- Nothing. -

+
Note:
-

- fiber::thread_affinity() is false - by default. -

+

@@ -228,10 +223,9 @@

#include <boost/fiber/interruption.hpp>
+
+void interruption_point();
 
-

- void interruption_point(); -

@@ -487,7 +481,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/fiber/fiber_mgmt/winfibers.html b/doc/html/fiber/fiber_mgmt/winfibers.html new file mode 100644 index 00000000..18ba9bd9 --- /dev/null +++ b/doc/html/fiber/fiber_mgmt/winfibers.html @@ -0,0 +1,50 @@ + + + +Using WinFiber-API + + + + + + + + + + + + + + + +
Boost C++ LibrariesHomeLibrariesPeopleFAQMore
+
+
+PrevUpHomeNext +
+
+ +

+ Because the TIB (thread information block) is not fully described in the + MSDN, it might be possible that not all required TIB-parts are swapped. With + compiler flag BOOST_USE_WINFIBERS + fiber uses internally the + Windows Fiber API. +

+
+ + + +
+
+
+PrevUpHomeNext +
+ + diff --git a/doc/html/fiber/fls.html b/doc/html/fiber/fls.html index 518f2eba..170fcf26 100644 --- a/doc/html/fiber/fls.html +++ b/doc/html/fiber/fls.html @@ -7,7 +7,7 @@ - + @@ -20,7 +20,7 @@

-PrevUpHomeNext +PrevUpHomeNext

@@ -326,7 +326,7 @@
-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/fiber/overview.html b/doc/html/fiber/overview.html index f4dc5412..54b1bcc5 100644 --- a/doc/html/fiber/overview.html +++ b/doc/html/fiber/overview.html @@ -142,9 +142,8 @@

- Boost.Fiber depends upon Boost.Chrono, - Boost.Context and Boost.Move. Boost version 1.55.0 - or greater is required. + Boost.Fiber depends upon Boost.Context. + Boost version 1.58.0 or greater is required.

[info This library is C++14-only!] diff --git a/doc/html/fiber/performance.html b/doc/html/fiber/performance.html index ccd51754..7f860a92 100644 --- a/doc/html/fiber/performance.html +++ b/doc/html/fiber/performance.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@


-PrevUpHomeNext +PrevUpHomeNext

@@ -29,7 +29,7 @@

Performance measurements were taken using std::chrono::highresolution_clock, with overhead corrections. The code was compiled using the build options: variant - = release, optimization = speed [2]. + = release, optimization = speed [1].

Table 1.1. Overhead of creating and joining

@@ -70,7 +70,7 @@

- 3 µs + 955 ns

@@ -108,12 +108,12 @@

- 16 µs + 20 µs

- 3 µs + 3.2 µs

@@ -141,12 +141,12 @@

- 32 µs + 38 µs

- 3 µs + 1.1 µs

@@ -179,7 +179,7 @@

- 4 µs + 2.4 µs

@@ -219,12 +219,12 @@

- 32.90 µs + 50.65 µs

- 3.769 µs + 3.76 µs

@@ -236,12 +236,12 @@

- 32.71 µs + 52.99 µs

- 2.789 µs + 2.78 µs

@@ -253,12 +253,12 @@

- 39.84 µs + 50.44 µs

- 2.450 µs + 2.45 µs

@@ -270,12 +270,12 @@

- 49.78 µs + 45.19 µs

- 2.919 µs + 2.91 µs

@@ -287,12 +287,12 @@

- 55.95 µs + 42.59 µs

- 3.607 µs + 3.60 µs

@@ -304,12 +304,12 @@

- 42.88 µs + 42.30 µs

- 4.579 µs + 4.57 µs

@@ -321,12 +321,317 @@

- 47.13 µs + 41.07 µs

- 4.219 µs + 4.21 µs +

+ + + +
+

+

+ Using internally atomics by applying BOOST_FIBER_USE_ATOMICS. +

+
+

Table 1.6. Overhead of creating and joining

+
++++++ + + + + + + + + + + + + +
+

+ thread +

+
+

+ fiber +

+
+

+ tbb +

+
+

+ qthread +

+
+

+ 31 µs +

+
+

+ 1.1 µs +

+
+

+ 570 ns +

+
+

+ 620 ns +

+
+
+
+

Table 1.7. Overhead of detach

+
++++ + + + + + + + + +
+

+ thread +

+
+

+ fiber +

+
+

+ 20 µs +

+
+

+ 3.2 µs +

+
+
+
+

Table 1.8. Overhead of yield

+
++++ + + + + + + + + +
+

+ thread +

+
+

+ fiber +

+
+

+ 38 µs +

+
+

+ 1.3 µs +

+
+
+
+

Table 1.9. Overhead of waiting on a future

+
++++ + + + + + + + + +
+

+ thread +

+
+

+ fiber +

+
+

+ 32 µs +

+
+

+ 3.0 µs +

+
+
+
+

Table 1.10. Scaling of creating and joining

+
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -335,7 +640,7 @@


-

[2] +

[1] Intel Core2 Q6700, x86_64, 3GHz

@@ -350,7 +655,7 @@
+

+ average of +

+
+

+ thread +

+
+

+ fiber +

+
+

+ 10 +

+
+

+ 50.65 µs +

+
+

+ 4.83 µs +

+
+

+ 50 +

+
+

+ 52.99 µs +

+
+

+ 4.84 µs +

+
+

+ 100 +

+
+

+ 50.44 µs +

+
+

+ 5.24 µs +

+
+

+ 500 +

+
+

+ 45.19 µs +

+
+

+ 4.86 µs +

+
+

+ 1000 +

+
+

+ 42.59 µs +

+
+

+ 5.04 µs +

+
+

+ 5000 +

+
+

+ 42.30 µs +

+
+

+ 5.07 µs +

+
+

+ 10000 +

+
+

+ 41.07 µs +

+
+

+ 5.12 µs


-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/fiber/rational.html b/doc/html/fiber/rational.html index 86ffc83c..f976e736 100644 --- a/doc/html/fiber/rational.html +++ b/doc/html/fiber/rational.html @@ -43,7 +43,7 @@ When a coroutine yields, it passes control directly to its caller (or, in the case of symmetric coroutines, a designated other coroutine). When a fiber blocks, it implicitly passes control to the fiber scheduler. Coroutines have no scheduler - because they need no scheduler. [3]. + because they need no scheduler. [2].

@@ -59,15 +59,6 @@

- fiber_managerwith free-functions -

-

- Some compiler store the this-pointer - on the stack so that the fiber, which has been migrated to another scheduler - (thread), access the invalid instance if it will be resumed from fiber_manager::run(). -

-

- synchronization between fibers running in different threads

@@ -81,36 +72,9 @@ in different schedulers (different threads) or running int the same scheduler (same thread).

-

- - migrating - fibers between threads -

-

- Fibers can be migrated between different schedulers, e.g. threads. The library - contains an example demonstrating how a scheduler could be implemented to allow - the migration of fibers. The example allows to move fibers from the ready-queue - (fibers with state READY, e.g. ready to be executed) of scheduler X to the ready-queue of scheduler Y. It is important that this operation is - thread-safe. If the fiber is put to the ready-queue of scheduler Y it might be selected for resumtion in the - next step, e.g. the fiber will be executed in the context of the thread running - scheudler Y. -

-

- - variadric - template args for async()/packaged_task<> -

-

- Variadric template args for asnyc() implies variadic args support for packaged_task<>. - Because C++03 does not provide variadric template args the author desided not - to support this featrure for asnyc() and packaged_task<> otherwise the template signature would - be look different btween C++03 and C++11. In further versions of this library - variadric template args will be supported for C++03 with the usage of pre-processor - macros and template specialization. -



-

[3] +

diff --git a/doc/html/fiber/scheduling.html b/doc/html/fiber/scheduling.html index e7d9bec3..fd9a403c 100644 --- a/doc/html/fiber/scheduling.html +++ b/doc/html/fiber/scheduling.html @@ -6,7 +6,7 @@ - + @@ -20,7 +20,7 @@
-PrevUpHomeNext +PrevUpHomeNext

@@ -128,6 +128,114 @@

+

+ To prevent the library from heap-allocating a default scheduler for a given + thread, that thread must call set_scheduling_algorithm() before + any other Boost.Fiber entry point. +

+
void thread_fn()
+{
+    my_fiber_scheduler mfs;
+    boost::fibers::set_scheduling_algorithm( & mfs);
+    ...
+}
+
+

+ A fiber-scheduler must implement interface sched_algorithm. + Boost.Fiber provides one scheduler: round_robin. +

+

+ You are explicitly permitted to code your own sched_algorithm subclass, + and to pass it to set_scheduling_algorithm(). +

+

+

+
+ + + Class + sched_algorithm +
+

+

+
#include <boost/fiber/algorithm.hpp>
+
+struct sched_algorithm
+{
+    virtual ~sched_algorithm() {}
+
+    virtual void awakened( detail::worker_fiber *) = 0;
+
+    virtual detail::worker_fiber * pick_next() = 0;
+
+    virtual void priority( detail::worker_fiber *, int) noexcept = 0;
+};
+
+

+

+
+ + + Member + function awakened() +
+

+

+
virtual void awakened( detail::worker_fiber * f) = 0;
+
+
+

+
+
Effects:
+

+ Marks fiber f, to be + ready to run. +

+
+
+

+

+
+ + + Member + function pick_next() +
+

+

+
virtual detail::worker_fiber * pick_next() = 0;
+
+
+

+
+
Effects:
+

+ Depending on the scheduling algorithm, this function returns the fiber + which is to be resumed next. +

+
+
+

+

+
+ + + Member + function priority() +
+

+

+
virtual void priority( detail::worker_fiber *, int) noexcept = 0;
+
+
+

+
+
Effects:
+

+ Resets the priority of fiber f. +

+
+

@@ -145,6 +253,14 @@ [info The example section provides a scheduler used for migrating fibers (work-stealing) between threads (different schedulers).]

+

+ < TODO > +

+

+ + customized + scheduler +

@@ -156,7 +272,7 @@

-PrevUpHomeNext +PrevUpHomeNext
diff --git a/doc/html/fiber/synchronization/channels.html b/doc/html/fiber/synchronization/channels.html index 83418d1c..57dd4123 100644 --- a/doc/html/fiber/synchronization/channels.html +++ b/doc/html/fiber/synchronization/channels.html @@ -159,8 +159,7 @@ bool is_empty(); - void push( value_type const& va); - void push( value_type && va); + channel_op_status push( value_type && va); channel_op_status pop( value_type & va); value_type value_pop(); @@ -275,8 +274,7 @@

-
void push( value_type const& va);
-void push( value_type && va);
+
channel_op_status push( value_type && va);
 

diff --git a/doc/html/fiber_HTML.manifest b/doc/html/fiber_HTML.manifest index 547fbd4e..8c47b3f0 100644 --- a/doc/html/fiber_HTML.manifest +++ b/doc/html/fiber_HTML.manifest @@ -4,6 +4,7 @@ fiber/fiber_mgmt.html fiber/fiber_mgmt/fiber.html fiber/fiber_mgmt/id.html fiber/fiber_mgmt/this_fiber.html +fiber/fiber_mgmt/winfibers.html fiber/scheduling.html fiber/stack.html fiber/synchronization.html @@ -16,7 +17,6 @@ fiber/synchronization/futures/future.html fiber/synchronization/futures/promise.html fiber/synchronization/futures/packaged_task.html fiber/fls.html -fiber/asio.html fiber/performance.html fiber/rational.html fiber/custom.html diff --git a/doc/html/index.html b/doc/html/index.html index c32259d2..24cd412a 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -43,6 +43,7 @@ fiber
Class fiber::id
Namespace this_fiber
+
Using WinFiber-API
Scheduling
Stack allocation
@@ -62,7 +63,6 @@
Fiber local storage
-
Example: asynchronous network I/O (boost.asio)
Performance
Rational
Customization
@@ -71,7 +71,7 @@
- +

Last revised: March 12, 2015 at 18:51:58 GMT

Last revised: June 19, 2015 at 19:37:16 GMT


diff --git a/doc/performance.qbk b/doc/performance.qbk index 717ee4a7..2fc98e8e 100644 --- a/doc/performance.qbk +++ b/doc/performance.qbk @@ -15,33 +15,67 @@ variant = release, optimization = speed [table Overhead of creating and joining [[thread] [fiber] [tbb] [qthread]] - [[31 \u00b5s] [1.5 \u00b5s] [570 ns] [620 ns]] + [[31 \u00b5s] [955 ns] [570 ns] [620 ns]] ] [table Overhead of detach [[thread] [fiber]] - [[20 \u00b5s] [3 \u00b5s]] + [[20 \u00b5s] [3.2 \u00b5s]] ] [table Overhead of yield [[thread] [fiber]] - [[38 \u00b5s] [1.9 \u00b5s]] + [[38 \u00b5s] [1.1 \u00b5s]] ] [table Overhead of waiting on a future [[thread] [fiber]] - [[32 \u00b5s] [2.7 \u00b5s]] + [[32 \u00b5s] [2.4 \u00b5s]] ] [table Scaling of creating and joining [[average of] [thread] [fiber]] - [[10] [50.65 \u00b5s] [3.769 \u00b5s]] - [[50] [52.99 \u00b5s] [2.789 \u00b5s]] - [[100] [50.44 \u00b5s] [2.450 \u00b5s]] - [[500] [45.19 \u00b5s] [2.919 \u00b5s]] - [[1000] [42.59 \u00b5s] [3.607 \u00b5s]] - [[5000] [42.30 \u00b5s] [4.579 \u00b5s]] - [[10000] [41.07 \u00b5s] [4.219 \u00b5s]] + [[10] [50.65 \u00b5s] [3.76 \u00b5s]] + [[50] [52.99 \u00b5s] [2.78 \u00b5s]] + [[100] [50.44 \u00b5s] [2.45 \u00b5s]] + [[500] [45.19 \u00b5s] [2.91 \u00b5s]] + [[1000] [42.59 \u00b5s] [3.60 \u00b5s]] + [[5000] [42.30 \u00b5s] [4.57 \u00b5s]] + [[10000] [41.07 \u00b5s] [4.21 \u00b5s]] + +] + +Using internally atomics by applying BOOST_FIBER_USE_ATOMICS. + +[table Overhead of creating and joining + [[thread] [fiber] [tbb] [qthread]] + [[31 \u00b5s] [1.1 \u00b5s] [570 ns] [620 ns]] +] + +[table Overhead of detach + [[thread] [fiber]] + [[20 \u00b5s] [3.2 \u00b5s]] +] + +[table Overhead of yield + [[thread] [fiber]] + [[38 \u00b5s] [1.3 \u00b5s]] +] + +[table Overhead of waiting on a future + [[thread] [fiber]] + [[32 \u00b5s] [3.0 \u00b5s]] +] + +[table Scaling of creating and joining + [[average of] [thread] [fiber]] + [[10] [50.65 \u00b5s] [4.83 \u00b5s]] + [[50] [52.99 \u00b5s] [4.84 \u00b5s]] + [[100] [50.44 \u00b5s] [5.24 \u00b5s]] + [[500] [45.19 \u00b5s] [4.86 \u00b5s]] + [[1000] [42.59 \u00b5s] [5.04 \u00b5s]] + [[5000] [42.30 \u00b5s] [5.07 \u00b5s]] + [[10000] [41.07 \u00b5s] [5.12 \u00b5s]] ] diff --git a/include/boost/fiber/condition.hpp b/include/boost/fiber/condition.hpp index 6d35dbb5..356118b4 100644 --- a/include/boost/fiber/condition.hpp +++ b/include/boost/fiber/condition.hpp @@ -17,7 +17,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -40,7 +40,7 @@ enum class cv_status { class BOOST_FIBERS_DECL condition { private: -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) detail::spinlock splk_; #endif std::deque< fiber_context * > waiting_; @@ -68,7 +68,7 @@ public: void wait( LockType & lt) { fiber_context * f( detail::scheduler::instance()->active() ); try { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // lock spinlock std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -82,7 +82,7 @@ public: lt.unlock(); // suspend this fiber -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // locked spinlock will be released if this fiber // was stored inside schedulers's waiting-queue detail::scheduler::instance()->wait( lk); @@ -97,7 +97,7 @@ public: // lock external again before returning lt.lock(); } catch (...) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif std::deque< fiber_context * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); @@ -116,7 +116,7 @@ public: fiber_context * f( detail::scheduler::instance()->active() ); try { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // lock spinlock std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -131,13 +131,13 @@ public: // suspend this fiber // locked spinlock will be released if this fiber // was stored inside schedulers's waiting-queue -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) if ( ! detail::scheduler::instance()->wait_until( timeout_time, lk) ) { #else if ( ! detail::scheduler::instance()->wait_until( timeout_time) ) { #endif // this fiber was not notified before timeout -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // lock spinlock again std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -156,7 +156,7 @@ public: // lock external again before returning lt.lock(); } catch (...) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif std::deque< fiber_context * >::iterator i( std::find( waiting_.begin(), waiting_.end(), f) ); diff --git a/include/boost/fiber/fiber_context.hpp b/include/boost/fiber/fiber_context.hpp index f3b577f4..2d4c1d01 100644 --- a/include/boost/fiber/fiber_context.hpp +++ b/include/boost/fiber/fiber_context.hpp @@ -24,7 +24,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -79,7 +79,7 @@ private: typedef std::map< uintptr_t, fss_data > fss_data_t; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::atomic< std::size_t > use_count_; std::atomic< fiber_status > state_; std::atomic< int > flags_; @@ -101,7 +101,7 @@ private: use_count_( 1), // allocated on stack state_( fiber_status::running), flags_( flag_main_fiber), -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif ctx_( context::execution_context::current() ), @@ -121,7 +121,7 @@ private: use_count_( 1), // allocated on stack state_( fiber_status::ready), flags_( 0), -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif ctx_( palloc, salloc, @@ -271,7 +271,7 @@ public: void set_terminated() noexcept { // TODO -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) fiber_status previous = state_.exchange( fiber_status::terminated); #else fiber_status previous = state_; @@ -283,7 +283,7 @@ public: void set_ready() noexcept { // TODO -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) fiber_status previous = state_.exchange( fiber_status::ready); #else fiber_status previous = state_; @@ -295,7 +295,7 @@ public: void set_running() noexcept { // TODO -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) fiber_status previous = state_.exchange( fiber_status::running); #else fiber_status previous = state_; @@ -307,7 +307,7 @@ public: void set_waiting() noexcept { // TODO -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) fiber_status previous = state_.exchange( fiber_status::waiting); #else fiber_status previous = state_; diff --git a/include/boost/fiber/fiber_manager.hpp b/include/boost/fiber/fiber_manager.hpp index 596848ec..d29af5d7 100644 --- a/include/boost/fiber/fiber_manager.hpp +++ b/include/boost/fiber/fiber_manager.hpp @@ -14,7 +14,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -58,7 +58,7 @@ public: void run(); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) void wait( std::unique_lock< detail::spinlock > &); bool wait_until( std::chrono::high_resolution_clock::time_point const&, diff --git a/include/boost/fiber/mutex.hpp b/include/boost/fiber/mutex.hpp index 53326644..eee236e8 100644 --- a/include/boost/fiber/mutex.hpp +++ b/include/boost/fiber/mutex.hpp @@ -12,7 +12,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -31,7 +31,7 @@ private: unlocked }; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) detail::spinlock splk_; #endif mutex_status state_; diff --git a/include/boost/fiber/operations.hpp b/include/boost/fiber/operations.hpp index 139bc3f8..9818cda7 100644 --- a/include/boost/fiber/operations.hpp +++ b/include/boost/fiber/operations.hpp @@ -13,7 +13,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -38,7 +38,7 @@ void yield() { template< typename Clock, typename Duration > void sleep_until( std::chrono::time_point< Clock, Duration > const& sleep_time) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) fibers::detail::spinlock splk; std::unique_lock< fibers::detail::spinlock > lk( splk); fibers::detail::scheduler::instance()->wait_until( sleep_time, lk); diff --git a/include/boost/fiber/recursive_mutex.hpp b/include/boost/fiber/recursive_mutex.hpp index 822aba98..1adb0d90 100644 --- a/include/boost/fiber/recursive_mutex.hpp +++ b/include/boost/fiber/recursive_mutex.hpp @@ -15,7 +15,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -34,7 +34,7 @@ private: unlocked }; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) detail::spinlock splk_; #endif mutex_status state_; diff --git a/include/boost/fiber/recursive_timed_mutex.hpp b/include/boost/fiber/recursive_timed_mutex.hpp index 80f1f4ca..1cbb4e7d 100644 --- a/include/boost/fiber/recursive_timed_mutex.hpp +++ b/include/boost/fiber/recursive_timed_mutex.hpp @@ -17,7 +17,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -36,7 +36,7 @@ private: unlocked }; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) detail::spinlock splk_; #endif mutex_status state_; diff --git a/include/boost/fiber/timed_mutex.hpp b/include/boost/fiber/timed_mutex.hpp index 636b07dd..43b91da3 100644 --- a/include/boost/fiber/timed_mutex.hpp +++ b/include/boost/fiber/timed_mutex.hpp @@ -14,7 +14,7 @@ #include #include -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) # include #endif #include @@ -33,7 +33,7 @@ private: unlocked }; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) detail::spinlock splk_; #endif mutex_status state_; diff --git a/performance/fiber/Jamfile.v2 b/performance/fiber/Jamfile.v2 index 70333c57..1d328863 100644 --- a/performance/fiber/Jamfile.v2 +++ b/performance/fiber/Jamfile.v2 @@ -44,3 +44,7 @@ exe overhead_yield exe overhead_future : overhead_future.cpp ; + +exe scale_join + : scale_join.cpp + ; diff --git a/src/condition.cpp b/src/condition.cpp index b1ccc5f2..2cd77aed 100644 --- a/src/condition.cpp +++ b/src/condition.cpp @@ -16,7 +16,7 @@ namespace boost { namespace fibers { condition::condition() : -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif waiting_() { @@ -30,7 +30,7 @@ void condition::notify_one() { fiber_context * f( nullptr); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); // get one waiting fiber if ( ! waiting_.empty() ) { @@ -56,7 +56,7 @@ void condition::notify_all() { std::deque< fiber_context * > waiting; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); // get all waiting fibers waiting.swap( waiting_); diff --git a/src/fiber_context.cpp b/src/fiber_context.cpp index 5fa64bda..096986b9 100644 --- a/src/fiber_context.cpp +++ b/src/fiber_context.cpp @@ -35,7 +35,7 @@ fiber_context::release() { std::vector< fiber_context * > waiting; // get all waiting fibers -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_.lock(); waiting.swap( waiting_); splk_.unlock(); @@ -61,7 +61,7 @@ bool fiber_context::join( fiber_context * f) { BOOST_ASSERT( nullptr != f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif if ( is_terminated() ) { diff --git a/src/fiber_manager.cpp b/src/fiber_manager.cpp index 330c4177..80acdb0e 100644 --- a/src/fiber_manager.cpp +++ b/src/fiber_manager.cpp @@ -128,7 +128,7 @@ fiber_manager::run() { } } -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) void fiber_manager::wait( std::unique_lock< detail::spinlock > & lk) { wait_until( diff --git a/src/mutex.cpp b/src/mutex.cpp index bd1166c0..09d5f981 100644 --- a/src/mutex.cpp +++ b/src/mutex.cpp @@ -34,7 +34,7 @@ mutex::lock_if_unlocked_() { } mutex::mutex() : -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif state_( mutex_status::unlocked), @@ -52,7 +52,7 @@ mutex::lock() { fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -64,7 +64,7 @@ mutex::lock() { BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber detail::scheduler::instance()->wait( lk); #else @@ -76,7 +76,7 @@ mutex::lock() { bool mutex::try_lock() { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -84,7 +84,7 @@ mutex::try_lock() { return true; } -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif // let other fiber release the lock @@ -97,7 +97,7 @@ mutex::unlock() { BOOST_ASSERT( mutex_status::locked == state_); BOOST_ASSERT( this_fiber::get_id() == owner_); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif fiber_context * f( nullptr); @@ -108,7 +108,7 @@ mutex::unlock() { } owner_ = fiber_context::id(); state_ = mutex_status::unlocked; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif if ( nullptr != f) { diff --git a/src/recursive_mutex.cpp b/src/recursive_mutex.cpp index a4dad734..54662406 100644 --- a/src/recursive_mutex.cpp +++ b/src/recursive_mutex.cpp @@ -38,7 +38,7 @@ recursive_mutex::lock_if_unlocked_() { } recursive_mutex::recursive_mutex() : -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif state_( mutex_status::unlocked), @@ -58,7 +58,7 @@ recursive_mutex::lock() { fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -70,7 +70,7 @@ recursive_mutex::lock() { BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber detail::scheduler::instance()->wait( lk); #else @@ -82,7 +82,7 @@ recursive_mutex::lock() { bool recursive_mutex::try_lock() { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -90,7 +90,7 @@ recursive_mutex::try_lock() { return true; } -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif // let other fiber release the lock @@ -103,7 +103,7 @@ recursive_mutex::unlock() { BOOST_ASSERT( mutex_status::locked == state_); BOOST_ASSERT( this_fiber::get_id() == owner_); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif fiber_context * f( nullptr); @@ -115,7 +115,7 @@ recursive_mutex::unlock() { } owner_ = fiber_context::id(); state_ = mutex_status::unlocked; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif if ( nullptr != f) { diff --git a/src/recursive_timed_mutex.cpp b/src/recursive_timed_mutex.cpp index 4fb44038..1f54c4af 100644 --- a/src/recursive_timed_mutex.cpp +++ b/src/recursive_timed_mutex.cpp @@ -38,7 +38,7 @@ recursive_timed_mutex::lock_if_unlocked_() { } recursive_timed_mutex::recursive_timed_mutex() : -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif state_( mutex_status::unlocked), @@ -58,7 +58,7 @@ recursive_timed_mutex::lock() { fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -70,7 +70,7 @@ recursive_timed_mutex::lock() { BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber detail::scheduler::instance()->wait( lk); #else @@ -82,7 +82,7 @@ recursive_timed_mutex::lock() { bool recursive_timed_mutex::try_lock() { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -90,7 +90,7 @@ recursive_timed_mutex::try_lock() { return true; } -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif // let other fiber release the lock @@ -103,7 +103,7 @@ recursive_timed_mutex::try_lock_until( std::chrono::high_resolution_clock::time_ fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -119,7 +119,7 @@ recursive_timed_mutex::try_lock_until( std::chrono::high_resolution_clock::time_ BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber until notified or timed-out if ( ! detail::scheduler::instance()->wait_until( timeout_time, lk) ) { lk.lock(); @@ -150,7 +150,7 @@ recursive_timed_mutex::unlock() { BOOST_ASSERT( mutex_status::locked == state_); BOOST_ASSERT( this_fiber::get_id() == owner_); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif fiber_context * f( nullptr); @@ -162,7 +162,7 @@ recursive_timed_mutex::unlock() { } owner_ = fiber_context::id(); state_ = mutex_status::unlocked; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif if ( nullptr != f) { diff --git a/src/timed_mutex.cpp b/src/timed_mutex.cpp index f5971b1a..f2399f8a 100644 --- a/src/timed_mutex.cpp +++ b/src/timed_mutex.cpp @@ -34,7 +34,7 @@ timed_mutex::lock_if_unlocked_() { } timed_mutex::timed_mutex() : -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) splk_(), #endif state_( mutex_status::unlocked), @@ -52,7 +52,7 @@ timed_mutex::lock() { fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -64,7 +64,7 @@ timed_mutex::lock() { BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber detail::scheduler::instance()->wait( lk); #else @@ -76,7 +76,7 @@ timed_mutex::lock() { bool timed_mutex::try_lock() { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -84,7 +84,7 @@ timed_mutex::try_lock() { return true; } -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif // let other fiber release the lock @@ -97,7 +97,7 @@ timed_mutex::try_lock_until( std::chrono::high_resolution_clock::time_point cons fiber_context * f( detail::scheduler::instance()->active() ); BOOST_ASSERT( nullptr != f); for (;;) { -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif @@ -113,7 +113,7 @@ timed_mutex::try_lock_until( std::chrono::high_resolution_clock::time_point cons BOOST_ASSERT( waiting_.end() == std::find( waiting_.begin(), waiting_.end(), f) ); waiting_.push_back( f); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) // suspend this fiber until notified or timed-out if ( ! detail::scheduler::instance()->wait_until( timeout_time, lk) ) { lk.lock(); @@ -144,7 +144,7 @@ timed_mutex::unlock() { BOOST_ASSERT( mutex_status::locked == state_); BOOST_ASSERT( this_fiber::get_id() == owner_); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) std::unique_lock< detail::spinlock > lk( splk_); #endif fiber_context * f( nullptr); @@ -155,7 +155,7 @@ timed_mutex::unlock() { } owner_ = fiber_context::id(); state_ = mutex_status::unlocked; -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) lk.unlock(); #endif if ( nullptr != f) { diff --git a/test/test_condition_mt.cpp b/test/test_condition_mt.cpp index 2a8f4e4f..6a9977c8 100644 --- a/test/test_condition_mt.cpp +++ b/test/test_condition_mt.cpp @@ -135,7 +135,7 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* []) boost::unit_test::test_suite * test = BOOST_TEST_SUITE("Boost.Fiber: multithreaded condition test suite"); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) test->add( BOOST_TEST_CASE( & test_one_waiter_notify_one) ); test->add( BOOST_TEST_CASE( & test_two_waiter_notify_all) ); #else diff --git a/test/test_futures_mt.cpp b/test/test_futures_mt.cpp index 20ca3b46..2a631d48 100644 --- a/test/test_futures_mt.cpp +++ b/test/test_futures_mt.cpp @@ -61,7 +61,7 @@ boost::unit_test_framework::test_suite* init_unit_test_suite(int, char*[]) boost::unit_test_framework::test_suite* test = BOOST_TEST_SUITE("Boost.Fiber: futures-mt test suite"); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) for ( int i = 0; i < 50; ++i) { test->add(BOOST_TEST_CASE(test_async)); } #else diff --git a/test/test_mutex_mt.cpp b/test/test_mutex_mt.cpp index 8f549fb5..964d1714 100644 --- a/test/test_mutex_mt.cpp +++ b/test/test_mutex_mt.cpp @@ -137,7 +137,7 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* []) boost::unit_test::test_suite * test = BOOST_TEST_SUITE("Boost.Fiber: multithreaded mutex test suite"); -#if defined(BOOST_FIBERS_THREADSAFE) +#if defined(BOOST_FIBERS_USE_ATOMICS) test->add( BOOST_TEST_CASE( & test_mutex) ); test->add( BOOST_TEST_CASE( & test_recursive_mutex) ); test->add( BOOST_TEST_CASE( & test_recursive_timed_mutex) );