mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-16 13:22:17 +00:00
Add a note to the condition_variable::wait_for(..., pred) overload. fiber_specific_ptr::reset() has no default argument. Remove mention of launch policy deferred, since no API accepts a launch policy argument. Copy construction or copy assignment of a shared_future leaves other.valid() unchanged. It won't be 'true' unless it was 'true' before. Mention that [shared_]future::get_exception_ptr() does not invalidate. Note that 'blocks' and 'suspends' are used interchangeably. Add some cross-references; add link to std::allocator_arg_t. Clarify the cross-reference to the paragraph describing BOOST_FIBERS_NO_ATOMICS. Reformat some overly-long source lines.
916 lines
29 KiB
Plaintext
916 lines
29 KiB
Plaintext
[/
|
|
(C) Copyright 2007-8 Anthony Williams.
|
|
(C) Copyright 2011-12 Vicente J. Botet Escriba.
|
|
(C) Copyright 2013 Oliver Kowalke.
|
|
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).
|
|
]
|
|
|
|
[section:fiber_mgmt Fiber management]
|
|
|
|
[heading Synopsis]
|
|
|
|
#include <boost/fiber/all.hpp>
|
|
|
|
namespace boost {
|
|
namespace fibers {
|
|
|
|
class fiber;
|
|
bool operator<( fiber const& l, fiber const& r) noexcept;
|
|
void swap( fiber & l, fiber & r) noexcept;
|
|
|
|
struct sched_algorithm;
|
|
template< typename PROPS >
|
|
struct sched_algorithm_with_properties;
|
|
class round_robin;
|
|
template< typename SchedAlgo, typename ... Args >
|
|
void use_scheduling_algorithm( Args && ... args);
|
|
std::size_t ready_fibers();
|
|
|
|
template< typename Rep, typename Period >
|
|
void wait_interval( std::chrono::duration< Rep, Period > const& wait_interval) noexcept;
|
|
template< typename Rep, typename Period >
|
|
std::chrono::duration< Rep, Period > wait_interval() noexcept;
|
|
|
|
}
|
|
|
|
namespace this_fiber {
|
|
|
|
fibers::id get_id() noexcept;
|
|
void yield();
|
|
template< typename Clock, typename Duration >
|
|
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);
|
|
template< typename PROPS >
|
|
PROPS & properties();
|
|
|
|
void interruption_point();
|
|
bool interruption_requested() noexcept;
|
|
bool interruption_enabled() noexcept;
|
|
class disable_interruption;
|
|
class restore_interruption;
|
|
|
|
}}
|
|
|
|
|
|
[heading Tutorial]
|
|
|
|
Each __fiber__ represents a micro-thread which will be launched and managed
|
|
cooperatively by a scheduler. Objects of type __fiber__ are move-only.
|
|
|
|
boost::fibers::fiber f1; // not-a-fiber
|
|
|
|
void f() {
|
|
boost::fibers::fiber f2( some_fn);
|
|
|
|
f1 = std::move( f2); // f2 moved to f1
|
|
}
|
|
|
|
|
|
[heading Launching]
|
|
|
|
A new fiber is launched by passing an object of a callable type that can be
|
|
invoked with no parameters.
|
|
If the object must not be copied or moved, then ['std::ref] can be used to
|
|
pass in a reference to the function object. In this case, the user must ensure
|
|
that the referenced object outlives the newly-created fiber.
|
|
|
|
struct callable {
|
|
void operator()();
|
|
};
|
|
|
|
boost::fibers::fiber copies_are_safe() {
|
|
callable x;
|
|
return boost::fibers::fiber( x);
|
|
} // x is destroyed, but the newly-created fiber has a copy, so this is OK
|
|
|
|
boost::fibers::fiber oops() {
|
|
callable x;
|
|
return boost::fibers::fiber( std::ref( x) );
|
|
} // x is destroyed, but the newly-created fiber still has a reference
|
|
// this leads to undefined behaviour
|
|
|
|
The spawned __fiber__ does not immediately start running. It is enqueued in
|
|
the list of ready-to-run fibers, and will run when the scheduler gets around
|
|
to it.
|
|
|
|
|
|
[#exceptions]
|
|
[heading Exceptions]
|
|
|
|
An exception escaping from the function or callable object passed to the __fiber__
|
|
constructor calls `std::terminate()`.
|
|
If you need to know which exception was thrown, use __future__ and
|
|
__packaged_task__.
|
|
|
|
|
|
[heading Detaching]
|
|
|
|
A __fiber__ can be detached by explicitly invoking the __detach__ member
|
|
function. After __detach__ is called on a fiber object, that object represents
|
|
__not_a_fiber__. The fiber object may then safely be destroyed.
|
|
|
|
boost::fibers::fiber( some_fn).detach();
|
|
|
|
__boost_fiber__ provides a number of ways to wait for a running fiber to
|
|
complete. You can coordinate even with a detached fiber using a [class_link
|
|
mutex], or [class_link condition_variable], or any of the other [link
|
|
synchronization synchronization objects] provided by the library.
|
|
|
|
If a detached fiber is still running when the thread's main fiber terminates,
|
|
that fiber will be [link interruption interrupted] and shut down.[footnote
|
|
This treatment of detached fibers depends on a detached fiber eventually
|
|
either terminating or reaching one of the specified __interruption_points__.
|
|
Note that since [ns_function_link this_fiber..yield] is ['not] an interruption
|
|
point, a detached fiber whose only interaction with the Fiber library is
|
|
`yield()` cannot cleanly be terminated.]
|
|
|
|
[heading Joining]
|
|
|
|
In order to wait for a fiber to finish, the __join__ member function of the
|
|
__fiber__ object can be used. __join__ will block until the __fiber__ object
|
|
has completed.
|
|
If the __fiber__ has already completed then __join__ returns immediately.
|
|
|
|
void some_fn() {
|
|
...
|
|
}
|
|
|
|
boost::fibers::fiber f( some_fn);
|
|
...
|
|
f.join();
|
|
|
|
If the fiber has already completed, then __join__ returns immediately and
|
|
the joined __fiber__ object becomes __not_a_fiber__.
|
|
|
|
|
|
[heading Destruction]
|
|
|
|
When a __fiber__ object representing a valid execution context (the fiber is
|
|
__joinable__) is destroyed, the program terminates. If you intend the fiber to
|
|
outlive the __fiber__ object that launched it, use the __detach__ method.
|
|
|
|
{
|
|
boost::fibers::fiber f( some_fn);
|
|
} // std::terminate() will be called
|
|
|
|
{
|
|
boost::fibers::fiber f(some_fn);
|
|
f.detach();
|
|
} // okay, program continues
|
|
|
|
|
|
[#interruption]
|
|
[heading Interruption]
|
|
|
|
A valid fiber can be interrupted by invoking its __interrupt__ member function.
|
|
The next time that fiber executes one of the specific __interruption_points__ with
|
|
interruption enabled, a __fiber_interrupted__ exception will be thrown.
|
|
If this exception is not caught, the fiber will be terminated, its stack unwound,
|
|
its stack objects properly destroyed.
|
|
|
|
With __disable_interruption__ a fiber can avoid being interrupted.
|
|
|
|
// interruption enabled at this point
|
|
{
|
|
boost::this_fiber::disable_interruption di1;
|
|
// interruption disabled
|
|
{
|
|
boost::this::fiber::disable_interruption di2;
|
|
// interruption still disabled
|
|
} // di2 destroyed; interruption state restored
|
|
// interruption still disabled
|
|
} // di destroyed; interruption state restored
|
|
// interruption enabled
|
|
|
|
At any point, the interruption state for the current thread can be queried by
|
|
calling __interruption_enabled__.
|
|
The following __interruption_points__ are defined and will throw
|
|
__fiber_interrupted__ if __interruption_requested__ and
|
|
__interruption_enabled__.
|
|
|
|
* __join__
|
|
* __barrier_wait__
|
|
* __cond_wait__
|
|
* __cond_wait_for__
|
|
* __cond_wait_until__
|
|
* __mutex_lock__ (__recursive_mutex__, __recursive_timed_mutex__, __timed_mutex__)
|
|
* __mutex_try_lock__ (__recursive_mutex__, __recursive_timed_mutex__, __timed_mutex__)
|
|
* __sleep_for__
|
|
* __sleep_until__
|
|
* __interruption_point__
|
|
* [member_link bounded_channel..push]
|
|
* [member_link bounded_channel..try_push]
|
|
* [member_link bounded_channel..push_wait_for]
|
|
* [member_link bounded_channel..push_wait_until]
|
|
* [member_link bounded_channel..pop]
|
|
* [member_link bounded_channel..try_pop]
|
|
* [member_link bounded_channel..value_pop]
|
|
* [member_link bounded_channel..pop_wait_for]
|
|
* [member_link bounded_channel..pop_wait_until]
|
|
* [member_link unbounded_channel..push]
|
|
* [member_link unbounded_channel..pop]
|
|
* [member_link unbounded_channel..try_pop]
|
|
* [member_link unbounded_channel..value_pop]
|
|
* [member_link unbounded_channel..pop_wait_for]
|
|
* [member_link unbounded_channel..pop_wait_until]
|
|
* [member_link future..wait]
|
|
* [member_link future..get]
|
|
* [member_link future..get_exception_ptr]
|
|
* [member_link shared_future..wait]
|
|
* [member_link shared_future..get]
|
|
* [member_link shared_future..get_exception_ptr]
|
|
|
|
[#class_fiber_id]
|
|
[heading Fiber IDs]
|
|
|
|
Objects of class __fiber_id__ can be used to identify fibers. Each running
|
|
__fiber__ has a unique __fiber_id__ obtainable from the corresponding __fiber__
|
|
by calling the __get_id__ member function.
|
|
Objects of class __fiber_id__ can be copied, and used as keys in associative
|
|
containers: the full range of comparison operators is provided.
|
|
They can also be written to an output stream using the stream insertion
|
|
operator, though the output format is unspecified.
|
|
|
|
Each instance of __fiber_id__ either refers to some fiber, or __not_a_fiber__.
|
|
Instances that refer to __not_a_fiber__ compare equal to each other, but
|
|
not equal to any instances that refer to an actual fiber. The comparison
|
|
operators on __fiber_id__ yield a total order for every non-equal __fiber_id__.
|
|
|
|
|
|
[#class_fiber]
|
|
[section:fiber Class `fiber`]
|
|
|
|
#include <boost/fiber/fiber.hpp>
|
|
|
|
class fiber {
|
|
public:
|
|
class id;
|
|
|
|
fiber() noexcept;
|
|
|
|
template< typename Fn, typename ... Args >
|
|
explicit fiber( Fn && fn, Args && ... args);
|
|
|
|
template< typename StackAllocator, typename Fn, typename ... Args >
|
|
explicit fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args);
|
|
|
|
~fiber();
|
|
|
|
fiber( fiber const& other) = delete;
|
|
|
|
fiber & operator=( fiber const& other) = delete;
|
|
|
|
fiber( fiber && other) noexcept;
|
|
|
|
fiber & operator=( fiber && other) noexcept;
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
bool operator!() const noexcept;
|
|
|
|
void swap( fiber & other) noexcept;
|
|
|
|
bool joinable() const noexcept;
|
|
|
|
id get_id() const noexcept;
|
|
|
|
void detach() noexcept;
|
|
|
|
void join();
|
|
|
|
void interrupt() noexcept;
|
|
|
|
template< typename PROPS >
|
|
PROPS & properties();
|
|
};
|
|
|
|
bool operator<( fiber const& l, fiber const& r) noexcept;
|
|
|
|
void swap( fiber & l, fiber & r) noexcept;
|
|
|
|
template< typename SchedAlgo, typename ... Args >
|
|
void use_scheduling_algorithm( Args && ... args);
|
|
|
|
std::size_t ready_fibers();
|
|
|
|
template< typename Rep, typename Period >
|
|
void wait_interval( std::chrono::duration< Rep, Period > const& wait_interval) noexcept;
|
|
template< typename Rep, typename Period >
|
|
std::chrono::duration< Rep, Period > wait_interval() noexcept;
|
|
|
|
|
|
[heading Default constructor]
|
|
|
|
fiber() noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Constructs a __fiber__ instance that refers to __not_a_fiber__.]]
|
|
[[Postconditions:] [`this->get_id() == fiber::id()`]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[#fiber_fiber]
|
|
[heading Constructor]
|
|
|
|
template< typename Fn, typename ... Args >
|
|
explicit fiber( Fn && fn, Args && ... args);
|
|
|
|
template< typename StackAllocator, typename Fn, typename ... Args >
|
|
explicit fiber( std::allocator_arg_t, StackAllocator salloc, Fn && fn, Args && ... args);
|
|
|
|
[variablelist
|
|
[[Preconditions:] [`Fn` must be copyable or movable.]]
|
|
[[Effects:] [`fn` is copied or moved into internal storage for access by the new fiber.]]
|
|
[[Postconditions:] [`*this` refers to the newly created fiber of execution.]]
|
|
[[Throws:] [__fiber_exception__ if an error occurs.]]
|
|
[[Note:] [StackAllocator is required to allocate a stack for the internal
|
|
__econtext__. If StackAllocator is not explicitly passed, a
|
|
__fixedsize_stack__ is used by default.]]
|
|
[[See also:] [__allocator_arg_t__, [link stack Stack allocation]]]
|
|
]
|
|
|
|
[heading Move constructor]
|
|
|
|
fiber( fiber && other) noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Transfers ownership of the fiber managed by `other` to the newly
|
|
constructed __fiber__ instance.]]
|
|
[[Postconditions:] [`other.get_id() == fiber::id()` and `get_id()` returns the
|
|
value of `other.get_id()` prior to the construction]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[heading Move assignment operator]
|
|
|
|
fiber & operator=( fiber && other) noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Transfers ownership of the fiber managed by `other` (if any) to
|
|
`*this`.]]
|
|
[[Postconditions:] [`other->get_id() == fiber::id()` and `get_id()` returns the
|
|
value of `other.get_id()` prior to the assignment.]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[heading Destructor]
|
|
|
|
~fiber();
|
|
|
|
[variablelist
|
|
[[Effects:] [If the fiber is __joinable__, calls std::terminate. Destroys
|
|
`*this`.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [The programmer must ensure that the destructor is never executed while
|
|
the fiber is still __joinable__. Even if you know (by calling
|
|
[member_link fiber..operator bool]) that the fiber has completed, you must
|
|
still call either __join__ or __detach__ before destroying the `fiber` object.]]
|
|
]
|
|
|
|
[member_heading fiber..joinable]
|
|
|
|
bool joinable() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if `*this` refers to a fiber of execution, which may or
|
|
may not have completed; otherwise `false`.]]
|
|
[[Throws:] [Nothing]]
|
|
[[See also:] [[member_link fiber..operator bool]]]
|
|
]
|
|
|
|
[member_heading fiber..join]
|
|
|
|
void join();
|
|
|
|
[variablelist
|
|
[[Preconditions:] [the fiber is __joinable__.]]
|
|
[[Effects:] [Waits for the referenced fiber of execution to complete.]]
|
|
[[Postconditions:] [The fiber of execution referenced on entry has completed.
|
|
`*this` no longer refers to any fiber of execution.]]
|
|
[[Throws:] [__fiber_interrupted__ if the current fiber is interrupted or
|
|
`system_error`]]
|
|
[[Error Conditions:] [
|
|
[*resource_deadlock_would_occur]: if `this->get_id() == boost::this_fiber::get_id()`.
|
|
[*invalid_argument]: if the fiber is not __joinable__.]]
|
|
[[Notes:] [`join()` is one of the predefined __interruption_points__.]]
|
|
]
|
|
|
|
[member_heading fiber..detach]
|
|
|
|
void detach();
|
|
|
|
[variablelist
|
|
[[Preconditions:] [the fiber is __joinable__.]]
|
|
[[Effects:] [The fiber of execution becomes detached, and no longer has an
|
|
associated __fiber__ object.]]
|
|
[[Postconditions:] [`*this` no longer refers to any fiber of execution.]]
|
|
[[Throws:] [`system_error`]]
|
|
[[Error Conditions:] [
|
|
[*invalid_argument]: if the fiber is not __joinable__.]]
|
|
]
|
|
|
|
[member_heading fiber..get_id]
|
|
|
|
fiber::id get_id() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [If `*this` refers to a fiber of execution, an instance of
|
|
__fiber_id__ that represents that fiber. Otherwise returns a
|
|
default-constructed __fiber_id__.]]
|
|
[[Throws:] [Nothing]]
|
|
[[See also:] [[ns_function_link this_fiber..get_id]]]
|
|
]
|
|
|
|
[member_heading fiber..interrupt]
|
|
|
|
void interrupt();
|
|
|
|
[variablelist
|
|
[[Effects:] [If `*this` refers to a fiber of execution, request that the fiber
|
|
will be interrupted the next time it enters one of the predefined
|
|
__interruption_points__ with interruption enabled, or if it is currently
|
|
__blocked__ in a call to one of the predefined __interruption_points__ with
|
|
interruption enabled.]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[template_member_heading fiber..properties]
|
|
|
|
template< typename PROPS >
|
|
PROPS & properties();
|
|
|
|
[variablelist
|
|
[[Preconditions:] [`*this` refers to a fiber of execution. [function_link
|
|
use_scheduling_algorithm] has been called from this thread with a subclass of
|
|
[template_link sched_algorithm_with_properties] with the same template
|
|
argument `PROPS`.]]
|
|
[[Returns:] [a reference to the scheduler properties instance for `*this`.]]
|
|
[[Throws:] [`std::bad_cast` if `use_scheduling_algorithm()` was called with a
|
|
`sched_algorithm_with_properties` subclass with some other template parameter
|
|
than `PROPS`.]]
|
|
[[Note:] [[template_link sched_algorithm_with_properties] provides a way for a
|
|
user-coded scheduler to associate extended properties, such as priority, with
|
|
a fiber instance. This method allows access to those user-provided properties.]]
|
|
[[See also:] [[link custom Customization]]]
|
|
]
|
|
|
|
[member_heading fiber..operator bool]
|
|
|
|
explicit operator bool() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if `*this` refers to a fiber of execution which has not
|
|
yet terminated, `false` otherwise. Compare to __joinable__, which does not
|
|
distinguish whether the referenced fiber of execution is still running.]]
|
|
[[Throws:] [Nothing]]
|
|
[[See also:] [__joinable__]]
|
|
]
|
|
|
|
[operator_heading fiber..operator_not..operator!]
|
|
|
|
bool operator!() const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if `*this` does not refer to a fiber of execution or if
|
|
its fiber of execution has terminated, `false` otherwise.]]
|
|
[[Throws:] [Nothing]]
|
|
[[See also:] [[member_link fiber..operator bool], __joinable__]]
|
|
]
|
|
|
|
[member_heading fiber..swap]
|
|
|
|
void swap( fiber & other) noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Exchanges the fiber of execution associated with `*this` and
|
|
`other`, so `*this` becomes associated with the fiber formerly associated with
|
|
`other`, and vice-versa.]]
|
|
[[Postconditions:] [`this->get_id()` returns the same value as `other.get_id()`
|
|
prior to the call. `other.get_id()` returns the same value as `this->get_id()`
|
|
prior to the call.]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[function_heading swap]
|
|
|
|
void swap( fiber & l, fiber & r) noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Same as `l.swap( r)`.]]
|
|
]
|
|
|
|
[function_heading use_scheduling_algorithm]
|
|
|
|
template< typename SchedAlgo, typename ... Args >
|
|
void use_scheduling_algorithm( Args && ... args);
|
|
|
|
[variablelist
|
|
[[Effects:] [Directs __boost_fiber__ to use `SchedAlgo`, which must be a
|
|
concrete subclass of __algo__, as the scheduling algorithm for all fibers in
|
|
the current thread. Pass any required `SchedAlgo` constructor arguments as
|
|
`args`.]]
|
|
[[Note:] [If you want a given thread to use a non-default scheduling
|
|
algorithm, make that thread call `use_scheduling_algorithm()` before any other
|
|
__boost_fiber__ entry point. If no scheduler has been set for the current
|
|
thread by the time __boost_fiber__ needs to use it, the library will
|
|
create a default [class_link round_robin] instance for this thread.]]
|
|
[[Throws:] [Nothing]]
|
|
[[See also:] [[link scheduling Scheduling], [link custom Customization]]]
|
|
]
|
|
|
|
[function_heading ready_fibers]
|
|
|
|
std::size_t ready_fibers();
|
|
|
|
[variablelist
|
|
[[Returns:] [the number of fibers ready to run.]]
|
|
[[Throws:] [Nothing]]
|
|
]
|
|
|
|
[function_heading wait_interval]
|
|
|
|
template< typename Rep, typename Period >
|
|
void wait_interval( std::chrono::duration< Rep, Period > const& wait_interval) noexcept;
|
|
template< typename Rep, typename Period >
|
|
std::chrono::duration< Rep, Period > wait_interval() noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [Sets/returns the wait interval used to suspend the thread if no
|
|
fibers are ready to run.]]
|
|
[[Throws:] [Nothing]]
|
|
[[Notes:] [This setting can be used to adjust the "niceness" of an idle
|
|
thread: a thread whose fibers are all currently blocked for various reasons.
|
|
The default for each thread, if not specified, is
|
|
`std::chrono::milliseconds(10)`. A longer `wait_interval()` causes an idle
|
|
thread to use less CPU. A shorter `wait_interval()` is more responsive to
|
|
fibers becoming ready. When a fiber becomes ready to resume, e.g. a mutex on
|
|
which it is blocked becomes available, control is not immediately passed to
|
|
that fiber; instead it is marked "ready to run." It won't actually resume
|
|
until the fiber manager wakes up to consult the scheduler. It could take as
|
|
long as `wait_interval()` before the fiber manager notices the fiber's
|
|
readiness. It is likely that the optimal setting for `wait_interval()` is
|
|
application-specific.]]
|
|
]
|
|
|
|
|
|
[endsect] [/ section Class fiber]
|
|
|
|
[#class_id]
|
|
[section:id Class fiber::id]
|
|
|
|
#include <boost/fiber/fiber.hpp>
|
|
|
|
class id {
|
|
public:
|
|
id() noexcept;
|
|
|
|
bool operator==( id const& other) const noexcept;
|
|
|
|
bool operator!=( id const& other) const noexcept;
|
|
|
|
bool operator<( id const& other) const noexcept;
|
|
|
|
bool operator>( id const& other) const noexcept;
|
|
|
|
bool operator<=( id const& other) const noexcept;
|
|
|
|
bool operator>=( id const& other) const noexcept;
|
|
|
|
template< typename charT, class traitsT >
|
|
friend std::basic_ostream< charT, traitsT > &
|
|
operator<<( std::basic_ostream< charT, traitsT > & os, id const& other);
|
|
};
|
|
|
|
[heading Constructor]
|
|
|
|
id() noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Represents an instance of __not_a_fiber__.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_equal..operator==]
|
|
|
|
bool operator==( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if `*this` and `other` represent the same fiber,
|
|
or both represent __not_a_fiber__, `false` otherwise.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_not_equal..operator!=]
|
|
|
|
bool operator!=( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [[`! (other == * this)]]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_less..operator<]
|
|
|
|
bool operator<( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if `*this != other` is true and the
|
|
implementation-defined total order of `fiber::id` values places `*this` before
|
|
`other`, false otherwise.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_greater..operator>]
|
|
|
|
bool operator>( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`other < * this`]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_less_equal..operator<=]
|
|
|
|
bool operator<=( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`! (other < * this)`]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[operator_heading id..operator_greater_equal..operator>=]
|
|
|
|
bool operator>=( id const& other) const noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`! (* this < other)`]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[heading operator<<]
|
|
|
|
template< typename charT, class traitsT >
|
|
std::basic_ostream< charT, traitsT > &
|
|
operator<<( std::basic_ostream< charT, traitsT > & os, id const& other);
|
|
|
|
[variablelist
|
|
[[Efects:] [Writes the representation of `other` to stream `os`.]]
|
|
[[Returns:] [`os`]]
|
|
]
|
|
|
|
|
|
[endsect] [/ section Class fiber::id]
|
|
|
|
|
|
[section:this_fiber Namespace this_fiber]
|
|
|
|
namespace boost {
|
|
namespace this_fiber {
|
|
|
|
fibers::fiber::id get_id() noexcept;
|
|
void yield();
|
|
template< typename Clock, typename Duration >
|
|
void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time)
|
|
template< typename Rep, typename Period >
|
|
void sleep_for( std::chrono::duration< Rep, Period > const& timeout_duration);
|
|
template< typename PROPS >
|
|
PROPS & properties();
|
|
|
|
void interruption_point();
|
|
bool interruption_requested() noexcept;
|
|
bool interruption_enabled() noexcept;
|
|
class disable_interruption;
|
|
class restore_interruption;
|
|
|
|
}}
|
|
|
|
[ns_function_heading this_fiber..get_id]
|
|
|
|
#include <boost/fiber/operations.hpp>
|
|
|
|
fiber::id get_id() noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [An instance of __fiber_id__ that represents the currently
|
|
executing fiber.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..sleep_until]
|
|
|
|
#include <boost/fiber/operations.hpp>
|
|
|
|
template< typename Clock, typename Duration >
|
|
void sleep_until( std::chrono::time_point< Clock, Duration > const& abs_time)
|
|
|
|
[variablelist
|
|
[[Effects:] [Suspends the current fiber until the time point specified by
|
|
`abs_time` has been reached.]]
|
|
[[Throws:] [__fiber_interrupted__ if the current fiber is interrupted.]]
|
|
[[Note:] [`sleep_until()` is one of the predefined __interruption_points__.]]
|
|
[[Note:][The current fiber will not resume before `abs_time`, but there are no
|
|
guarantees about how soon after `abs_time` it might resume.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..sleep_for]
|
|
|
|
#include <boost/fiber/operations.hpp>
|
|
|
|
template< class Rep, class Period >
|
|
void sleep_for( std::chrono::duration< Rep, Period > const& rel_time);
|
|
|
|
[variablelist
|
|
[[Effects:] [Suspends the current fiber until the time duration specified by
|
|
`rel_time` has elapsed.]]
|
|
[[Throws:] [Any exceptions thrown by operations of `std::chrono::duration<Rep,
|
|
Period>`. __fiber_interrupted__ if the current fiber is interrupted.]]
|
|
[[Note:] [`sleep_for()` is one of the predefined __interruption_points__.]]
|
|
[[Note:][The current fiber will not resume before `rel_time` has elapsed, but
|
|
there are no guarantees about how soon after that it might resume.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..yield]
|
|
|
|
#include <boost/fiber/operations.hpp>
|
|
|
|
void yield();
|
|
|
|
[variablelist
|
|
[[Effects:] [Reliquishes execution control, allowing other fibers to run.]]
|
|
[[Throws:] [__fiber_resource_error__ if an error occurs.]]
|
|
[[Note:] [`yield()` is ['not] an interruption point. A fiber that calls
|
|
`yield()` is not suspended: it is immediately passed to the scheduler as ready
|
|
to run.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..properties]
|
|
|
|
#include <boost/fiber/operations.hpp>
|
|
|
|
template< typename PROPS >
|
|
PROPS & properties();
|
|
|
|
[variablelist
|
|
[[Preconditions:] [[function_link use_scheduling_algorithm] has been called
|
|
from this thread with a subclass of [template_link
|
|
sched_algorithm_with_properties] with the same template argument `PROPS`.]]
|
|
[[Returns:] [a reference to the scheduler properties instance for the
|
|
currently running fiber.]]
|
|
[[Throws:] [`std::bad_cast` if `use_scheduling_algorithm()` was called with a
|
|
`sched_algorithm_with_properties` subclass with some other template parameter
|
|
than `PROPS`.]]
|
|
[[Note:] [[template_link sched_algorithm_with_properties] provides a way for a
|
|
user-coded scheduler to associate extended properties, such as priority, with
|
|
a fiber instance. This function allows access to those user-provided
|
|
properties.]]
|
|
[[Note:] [The first time this function is called from the main fiber of a
|
|
thread, it may internally yield, permitting other fibers to run.]]
|
|
[[See also:] [[link custom Customization]]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..interruption_point]
|
|
|
|
#include <boost/fiber/interruption.hpp>
|
|
|
|
void interruption_point();
|
|
|
|
[variablelist
|
|
[[Effects:] [Check to see if the current fiber has been interrupted.]]
|
|
[[Throws:] [__fiber_interrupted__ if __interruption_enabled__ and
|
|
__interruption_requested__ both return `true`.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..interruption_requested]
|
|
|
|
#include <boost/fiber/interruption.hpp>
|
|
|
|
bool interruption_requested() noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if interruption has been requested for the current fiber,
|
|
`false` otherwise.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[ns_function_heading this_fiber..interruption_enabled]
|
|
|
|
#include <boost/fiber/interruption.hpp>
|
|
|
|
bool interruption_enabled() noexcept;
|
|
|
|
[variablelist
|
|
[[Returns:] [`true` if interruption is enabled for the current fiber,
|
|
`false` otherwise.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:][Interruption is enabled by default.]]
|
|
]
|
|
|
|
[class_heading disable_interruption]
|
|
|
|
#include <boost/fiber/interruption.hpp>
|
|
|
|
class disable_interruption {
|
|
public:
|
|
disable_interruption() noexcept;
|
|
~disable_interruption() noexcept;
|
|
disable_interruption(const disable_interruption&) = delete;
|
|
disable_interruption& operator=(const disable_interruption&) = delete;
|
|
};
|
|
|
|
[heading Constructor]
|
|
|
|
disable_interruption() noexcept;
|
|
|
|
[variablelist
|
|
[[Effects:] [Stores the current state of __interruption_enabled__ and disables
|
|
interruption for the current fiber.]]
|
|
[[Postconditions:] [__interruption_enabled__ returns `false` for the current
|
|
fiber.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[heading Destructor]
|
|
|
|
~disable_interruption() noexcept;
|
|
|
|
[variablelist
|
|
[[Preconditions:] [Must be called from the same fiber on which `*this` was
|
|
constructed.]]
|
|
[[Effects:] [Restores the state of __interruption_enabled__ for the
|
|
current fiber to the state saved at construction of `*this`.]]
|
|
[[Postconditions:] [__interruption_enabled__ for the current fiber returns the
|
|
value stored by the constructor of `*this`.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
|
|
[class_heading restore_interruption]
|
|
|
|
#include <boost/fiber/interruption.hpp>
|
|
|
|
class restore_interruption {
|
|
public:
|
|
explicit restore_interruption(disable_interruption& disabler) noexcept;
|
|
~restore_interruption() noexcept;
|
|
restore_interruption(const restore_interruption&) = delete;
|
|
restore_interruption& operator=(const restore_interruption&) = delete;
|
|
};
|
|
|
|
[heading Constructor]
|
|
|
|
explicit restore_interruption(disable_interruption& disabler) noexcept;
|
|
|
|
[variablelist
|
|
[[Preconditions:] [Must be called from the same fiber on which `disabler` was
|
|
constructed.]]
|
|
[[Effects:] [Restores the current state of __interruption_enabled__ for the
|
|
current fiber to that saved in `disabler`.]]
|
|
[[Postconditions:] [__interruption_enabled__ for the current fiber returns the
|
|
value stored in the constructor of `disabler`.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[heading Destructor]
|
|
|
|
~restore_interruption() noexcept;
|
|
|
|
[variablelist
|
|
[[Preconditions:] [Must be called from the same fiber on which `*this` was
|
|
constructed.]]
|
|
[[Effects:] [Disables interruption for the current fiber.]]
|
|
[[Postconditions:] [__interruption_enabled__ for the current fiber returns
|
|
`false`.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
void foo() {
|
|
// interruption is enabled
|
|
{
|
|
boost::this_fiber::disable_interruption di;
|
|
// interruption is disabled
|
|
{
|
|
boost::this_fiber::restore_interruption ri( di);
|
|
// interruption now enabled
|
|
} // ri destroyed, interruption disable again
|
|
} // di destructed, interruption state restored
|
|
// interruption now enabled
|
|
}
|
|
|
|
[endsect] [/ section Namespace this_fiber]
|
|
|
|
|
|
[section:winfibers Using WinFiber-API]
|
|
|
|
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 (see also [@http://www.boost.org/doc/libs/release/libs/context/doc/html/context/econtext/winfibers.html Boost.Context WinFiber support]).
|
|
|
|
[endsect]
|
|
|
|
|
|
[endsect] [/ section Fiber Management]
|