diff --git a/doc/fls.qbk b/doc/fls.qbk index edb52996..32696ffe 100644 --- a/doc/fls.qbk +++ b/doc/fls.qbk @@ -77,11 +77,11 @@ will be used to destroy the fiber-local objects.]] [[Effects:] [Calls `this->reset()` to clean up the associated value for the current fiber, and destroys `*this`.]] [[Throws:] [Nothing.]] -[[Remarks:] [The requirement is due to the fact that in order to delete all -these instances, the implementation should be forced to maintain a list of all -the fibers having an associated specific ptr, which is against the goal of -fiber specific data. In general, a __fsp__ should outlive the fibers that use -it.]] +[[Remarks:] [The requirement is an implementation restriction. If the +destructor promised to delete instances for all fibers, the implementation +would be forced to maintain a list of all the fibers having an associated +specific ptr, which is against the goal of fiber specific data. In general, a +__fsp__ should outlive the fibers that use it.]] ] [note Care needs to be taken to ensure that any fibers still running after an instance of __fsp__ has been destroyed do not call any member functions on that @@ -95,7 +95,7 @@ instance.] [[Returns:] [The pointer associated with the current fiber.]] [[Throws:] [Nothing.]] ] -[note The initial value associated with an instance of __fsp__ is `NULL` for +[note The initial value associated with an instance of __fsp__ is `nullptr` for each fiber.] [operator_heading fiber_specific_ptr..operator_arrow..operator->] @@ -112,7 +112,7 @@ each fiber.] T& operator*() const; [variablelist -[[Requires:] [`this->get` is not `NULL`.]] +[[Requires:] [`this->get()` is not `nullptr`.]] [[Returns:] [`*(this->get())`]] [[Throws:] [Nothing.]] ] @@ -122,7 +122,7 @@ each fiber.] T* release(); [variablelist -[[Effects:] [Return `this->get()` and store `NULL` as the pointer associated +[[Effects:] [Return `this->get()` and store `nullptr` as the pointer associated with the current fiber without invoking the cleanup function.]] [[Postcondition:] [`this->get()==0`]] [[Throws:] [Nothing.]] @@ -133,7 +133,7 @@ with the current fiber without invoking the cleanup function.]] void reset(T* new_value=0); [variablelist -[[Effects:] [If `this->get()!=new_value` and `this->get()` is non-`NULL`, +[[Effects:] [If `this->get()!=new_value` and `this->get()` is not `nullptr`, invoke `delete this->get()` or `fn(this->get())` as appropriate. Store `new_value` as the pointer associated with the current fiber.]] [[Postcondition:] [`this->get()==new_value`]] diff --git a/doc/packaged_task.qbk b/doc/packaged_task.qbk index 9fab07aa..46a4ec71 100644 --- a/doc/packaged_task.qbk +++ b/doc/packaged_task.qbk @@ -11,6 +11,21 @@ A __packaged_task__ wraps a callable target that returns a value so that the return value can be computed asynchronously. +Conventional usage of `packaged_task<>` is like this: + +# Instantiate `packaged_task<>` with template arguments matching the signature + of the callable. Pass the callable to the [link packaged_task_packaged_task + constructor]. +# Call [member_link packaged_task..get_future] and capture the returned + [template_link future] instance. +# Launch a [class_link fiber] to run the new `packaged_task<>`, passing any + arguments required by the original callable. +# Call [member_link fiber..detach] on the newly-launched `fiber`. +# At some later point, retrieve the result from the `future<>`. + +This is, in fact, pretty much what [ns_function_link fibers..async] +encapsulates. + template< class R, typename ... Args > class packaged_task< R( Args ... ) > { public: @@ -34,10 +49,6 @@ return value can be computed asynchronously. void swap( packaged_task & other) noexcept; - operator safe_bool() const noexcept; - - bool operator!() const noexcept; - bool valid() const noexcept; future< R > get_future(); @@ -52,10 +63,12 @@ return value can be computed asynchronously. packaged_task(); [variablelist -[[Effects:] [Constructs an object of class `packaged_task` with no [link shared_state shared state].]] +[[Effects:] [Constructs an object of class `packaged_task` with no [link +shared_state shared state].]] [[Throws:] [Nothing.]] ] +[#packaged_task_packaged_task] [heading Templated constructor `template<> packaged_task()`] template< typename Fn > @@ -65,8 +78,8 @@ return value can be computed asynchronously. explicit packaged_task( std::allocator_arg_t, Allocator const& alloc, Fn && fn); [variablelist -[[Effects:] [Constructs an object of class `packaged_task` with a [link shared_state shared state] -and stores the callable target `fn` internally.]] +[[Effects:] [Constructs an object of class `packaged_task` with a [link +shared_state shared state] and stores the callable target `fn` internally.]] [[Throws:] [Nothing.]] [[Note:] [The signature of `Fn` should have a return type convertible to `R`.]] ] @@ -76,7 +89,8 @@ and stores the callable target `fn` internally.]] packaged_task( packaged_task && other) noexcept; [variablelist -[[Effects:] [Creates a packaged_task by moving the [link shared_state shared state] from `other`.]] +[[Effects:] [Creates a packaged_task by moving the [link shared_state shared +state] from `other`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -86,8 +100,9 @@ and stores the callable target `fn` internally.]] ~packaged_task(); [variablelist -[[Effects:] [Destroys `*this` and abandons the [link shared_state shared state] if shared state is -ready; otherwise stores __future_error__ with error condition __broken_promise__.]] +[[Effects:] [Destroys `*this` and abandons the [link shared_state shared +state] if shared state is ready; otherwise stores __future_error__ with error +condition __broken_promise__.]] [[Throws:] [Nothing.]] ] @@ -96,7 +111,8 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ packaged_task & operator=( packaged_task && other) noexcept; [variablelist -[[Effects:] [Transfers the ownership of [link shared_state shared state] to `*this`.]] +[[Effects:] [Transfers the ownership of [link shared_state shared state] to +`*this`.]] [[Postcondition:] [`other` contains no valid shared state.]] [[Throws:] [Nothing.]] ] @@ -106,25 +122,8 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ void swap( packaged_task & other) noexcept; [variablelist -[[Effects:] [Swaps the [link shared_state shared state] between other and `*this`.]] -[[Throws:] [Nothing.]] -] - -[member_heading packaged_task..operator safe_bool] - - operator safe_bool() const noexcept; - -[variablelist -[[Effects:] [Returns `true` if `*this` contains a non-empty [link shared_state shared state].]] -[[Throws:] [Nothing.]] -] - -[operator_heading packaged_task..operator_not..operator!] - - bool operator!() const noexcept; - -[variablelist -[[Effects:] [Returns `true` if `*this` contains an empty [link shared_state shared state].]] +[[Effects:] [Swaps the [link shared_state shared state] between other and +`*this`.]] [[Throws:] [Nothing.]] ] @@ -133,7 +132,8 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ bool valid() const noexcept; [variablelist -[[Effects:] [Returns `true` if `*this` contains a [link shared_state shared state].]] +[[Effects:] [Returns `true` if `*this` contains a [link shared_state shared +state].]] [[Throws:] [Nothing.]] ] @@ -152,8 +152,8 @@ ready; otherwise stores __future_error__ with error condition __broken_promise__ [variablelist [[Effects:] [Invokes the stored callable target. Any exception thrown by the -callable target `fn` is stored in the [link shared_state shared state]. Otherwise, the value returned -by `fn` is stored in the shared state.]] +callable target `fn` is stored in the [link shared_state shared state]. +Otherwise, the value returned by `fn` is stored in the shared state.]] [[Throws:] [__future_error__ with __no_state__.]] ] @@ -162,8 +162,8 @@ by `fn` is stored in the shared state.]] void reset(); [variablelist -[[Effects:] [Resets the [link shared_state shared state] and abondons the result of previous -executions. A new shared state is constructed.]] +[[Effects:] [Resets the [link shared_state shared state] and abondons the +result of previous executions. A new shared state is constructed.]] [[Throws:] [__future_error__ with __no_state__.]] ] diff --git a/doc/performance.qbk b/doc/performance.qbk index abadb23a..7889d4e5 100644 --- a/doc/performance.qbk +++ b/doc/performance.qbk @@ -13,70 +13,40 @@ The code was compiled using the build options: variant = release, optimization = speed [footnote Intel Core2 Q6700, x86_64, 3GHz]. -[table Overhead of creating and joining - [[thread] [fiber] [tbb] [qthread]] - [[31 \u00b5s] [1.1 \u00b5s] [570 ns] [620 ns]] +The columns labeled [*fiber (atomics)] were compiled with default fiber +synchronization, capable of synchronizing fibers running on different threads. +The columns labeled [*fiber (raw)] were compiled with [link cross_thread_sync +`BOOST_FIBERS_NO_ATOMICS`]. + +[table [@boost:/libs/fiber/performance/overhead_join.cpp Overhead of creating and joining] + [[thread] [fiber (atomics)] [fiber (raw)] [tbb] [qthread]] + [[31 \u00b5s] [1.1 \u00b5s] [955 ns] [570 ns] [620 ns]] ] -[table Overhead of detach - [[thread] [fiber]] - [[20 \u00b5s] [3.2 \u00b5s]] +[table [@boost:/libs/fiber/performance/overhead_detach.cpp Overhead of detach] + [[thread] [fiber (atomics)] [fiber (raw)]] + [[20 \u00b5s] [3.2 \u00b5s] [3.2 \u00b5s]] ] -[table Overhead of yield - [[thread] [fiber]] - [[38 \u00b5s] [1.3 \u00b5s]] +[table [@boost:/libs/fiber/performance/overhead_yield.cpp Overhead of yield] + [[thread] [fiber (atomics)] [fiber (raw)]] + [[38 \u00b5s] [1.3 \u00b5s] [1.1 \u00b5s]] ] -[table Overhead of waiting on a future - [[thread] [fiber]] - [[32 \u00b5s] [3.0 \u00b5s]] +[table [@boost:/libs/fiber/performance/overhead_future.cpp Overhead of waiting on a future] + [[thread] [fiber (atomics)] [fiber (raw)]] + [[32 \u00b5s] [3.0 \u00b5s] [2.4 \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]] - -] - -Using internally atomics by applying BOOST_FIBER_NO_ATOMICS. - -[table Overhead of creating and joining - [[thread] [fiber] [tbb] [qthread]] - [[31 \u00b5s] [955 ns] [570 ns] [620 ns]] -] - -[table Overhead of detach - [[thread] [fiber]] - [[20 \u00b5s] [3.2 \u00b5s]] -] - -[table Overhead of yield - [[thread] [fiber]] - [[38 \u00b5s] [1.1 \u00b5s]] -] - -[table Overhead of waiting on a future - [[thread] [fiber]] - [[32 \u00b5s] [2.4 \u00b5s]] -] - -[table Scaling of creating and joining - [[average of] [thread] [fiber]] - [[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]] - +[table [@boost:/libs/fiber/performance/scale_join.cpp Scaling of creating and joining] + [[average of] [thread] [fiber (atomics)] [fiber (raw)]] + [[10] [50.65 \u00b5s] [4.83 \u00b5s] [3.76 \u00b5s]] + [[50] [52.99 \u00b5s] [4.84 \u00b5s] [2.78 \u00b5s]] + [[100] [50.44 \u00b5s] [5.24 \u00b5s] [2.45 \u00b5s]] + [[500] [45.19 \u00b5s] [4.86 \u00b5s] [2.91 \u00b5s]] + [[1000] [42.59 \u00b5s] [5.04 \u00b5s] [3.60 \u00b5s]] + [[5000] [42.30 \u00b5s] [5.07 \u00b5s] [4.57 \u00b5s]] + [[10000] [41.07 \u00b5s] [5.12 \u00b5s] [4.21 \u00b5s]] ]