mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-12 12:02:54 +00:00
Merge pull request #44 from nat-goodspeed/develop
Review documentation for packaged_task, fls and performance.
This commit is contained in:
18
doc/fls.qbk
18
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`]]
|
||||
|
||||
@@ -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__.]]
|
||||
]
|
||||
|
||||
|
||||
@@ -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]]
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user