mirror of
https://github.com/boostorg/fiber.git
synced 2026-02-01 20:42:08 +00:00
251 lines
6.9 KiB
Plaintext
251 lines
6.9 KiB
Plaintext
[/
|
|
Copyright Oliver Kowalke 2013.
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or copy at
|
|
http://www.boost.org/LICENSE_1_0.txt
|
|
]
|
|
|
|
[section:queues Queues]
|
|
|
|
__boost_fiber__ provides a bounded and a unbounded queue suitable to
|
|
synchonize fibers via message passing.
|
|
|
|
typedef boost::fibers::unbounded_queue< int > queue_t;
|
|
|
|
void send( queue_t & queue)
|
|
{
|
|
for ( int i = 0; i < 5; ++i)
|
|
queue.put( i);
|
|
queue.deactivate();
|
|
}
|
|
|
|
void recv( queue_t & queue)
|
|
{
|
|
boost::optional< int > value;
|
|
while ( queue.take( value) )
|
|
{ std::cout << "received " << * value << std::endl; }
|
|
}
|
|
|
|
queue_t queue;
|
|
boost::fibers::fiber f1( boost::bind( send, ref( queue) ) );
|
|
boost::fibers::fiber f2( boost::bind( recv, ref( queue) ) );
|
|
|
|
f1.join();
|
|
f2.join();
|
|
|
|
[heading Template `unbounded_queue<>`]
|
|
|
|
#include <boost/fiber/unbounded_queue.hpp>
|
|
|
|
template< typename T >
|
|
class unbounded_queue
|
|
{
|
|
public:
|
|
unbounded_queue( unbounded_queue const& other) = delete;
|
|
unbounded_queue & operator=( unbounded_queue const& other) = delete;
|
|
|
|
bool active() const;
|
|
|
|
void deactivate();
|
|
|
|
bool empty();
|
|
|
|
void put( T const& t);
|
|
|
|
bool take( boost::optional< T > & va);
|
|
|
|
bool try_take( boost::optional< T > & va);
|
|
};
|
|
|
|
[heading Member function `active()`]
|
|
|
|
bool active() const;
|
|
|
|
[variablelist
|
|
[[Effects:] [Return `true` if queue is still usable.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [The queue is usable by default.]]
|
|
]
|
|
|
|
[heading Member function `deactivate()`]
|
|
|
|
void deactivate();
|
|
|
|
[variablelist
|
|
[[Effects:] [Deactivates the queue. No values can be put after calling
|
|
`this->deactivate`. Fibers blocked in `this->take()` will return.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [`deactivate()` is like closing a pipe. It informs waiting receivers
|
|
that no more values will arrive.]]
|
|
]
|
|
|
|
[heading Member function `empty()`]
|
|
|
|
bool empty();
|
|
|
|
[variablelist
|
|
[[Effects:] [Returns `true` if the queue currently contains no data.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [This condition is transient. An `empty()` queue can become
|
|
non-empty.]]
|
|
]
|
|
|
|
[heading Member function `put()`]
|
|
|
|
void put( T const& t);
|
|
|
|
[variablelist
|
|
[[Effects:] [Enqueues the value in the queue and wakes up a fiber waiting
|
|
for new data available from the queue.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [Oliver: this signature appears to impose a requirement that T be
|
|
copyable. Would it make sense to support move-only T?]]
|
|
]
|
|
|
|
[heading Member function `take()`]
|
|
|
|
bool take( boost::optional< T > & va);
|
|
|
|
[variablelist
|
|
[[Effects:] [Dequeues a value from the queue. If no data is available from the
|
|
queue the fiber gets suspended until at least one new item is enqueued (return
|
|
value `true` and va contains dequeued value) or the queue gets deactivated and
|
|
the function returns `false`.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [Oliver: is this an interruption point?]]
|
|
]
|
|
|
|
[heading Member function `try_take()`]
|
|
|
|
bool try_take( boost::optional< T > & va);
|
|
|
|
[variablelist
|
|
[[Effects:] [Dequeues a value from the queue. If no data can be retrieved from
|
|
the queue at this moment, the function returns `false`. Otherwise it returns
|
|
`true` and `va` contains the dequeued value.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [A return value of `false` does not distinguish between `empty()` and
|
|
`(! active())`.]]
|
|
]
|
|
|
|
|
|
[heading Template `bounded_queue<>`]
|
|
|
|
#include <boost/fiber/bounded_queue.hpp>
|
|
|
|
template< typename T >
|
|
class bounded_queue
|
|
{
|
|
public:
|
|
bounded_queue( bounded_queue const& other) = delete;
|
|
bounded_queue & operator=( bounded_queue const& other) = delete;
|
|
|
|
bounded_queue( std::size_t wm);
|
|
|
|
bounded_queue( std::size_t hwm, std::size_t lwm);
|
|
|
|
bool active() const;
|
|
|
|
void deactivate();
|
|
|
|
bool empty();
|
|
|
|
void put( T const& t);
|
|
|
|
bool take( boost::optional< T > & va);
|
|
|
|
bool try_take( boost::optional< T > & va);
|
|
};
|
|
|
|
[heading Constructor]
|
|
|
|
bounded_queue( std::size_t wm);
|
|
bounded_queue( std::size_t hwm, std::size_t lwm);
|
|
|
|
[variablelist
|
|
[[Effects:] [Constructs an object of class `bounded_queue` which will contain
|
|
a maximum of `wm` items. The constructor with two arguments constructs an object
|
|
of class `bounded_queue` which will contain a high-watermark of `hwm` and a
|
|
low-watermark of `lwm` items.]]
|
|
[[Throws:] [Nothing.]]
|
|
]
|
|
|
|
[heading Member function `active()`]
|
|
|
|
bool active() const;
|
|
|
|
[variablelist
|
|
[[Effects:] [Return `true` if queue is still usable.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [The queue is usable by default.]]
|
|
]
|
|
|
|
[heading Member function `deactivate()`]
|
|
|
|
void deactivate();
|
|
|
|
[variablelist
|
|
[[Effects:] [Deactivates the queue. No values can be put after calling
|
|
`this->deactivate`. Fibers blocked in `this->take()` will return.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [`deactivate()` is like closing a pipe. It informs waiting receivers
|
|
that no more values will arrive.]]
|
|
]
|
|
|
|
[heading Member function `empty()`]
|
|
|
|
bool empty();
|
|
|
|
[variablelist
|
|
[[Effects:] [Returns `true` if the queue currently contains no data.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [This condition is transient. An `empty()` queue can become
|
|
non-empty.]]
|
|
[[Note:] [Oliver: wouldn't it make sense to have a corresponding `full()` method?]]
|
|
]
|
|
|
|
[heading Member function `put()`]
|
|
|
|
void put( T const& t);
|
|
|
|
[variablelist
|
|
[[Effects:] [Enqueues the value in the queue and wakes up a fiber waiting
|
|
for new data available from the queue. When the high water mark is reached, the
|
|
fiber putting the value will be supended until at least one item is
|
|
dequeued.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [Oliver: this signature appears to impose a requirement that T be
|
|
copyable. Would it make sense to support move-only T?]]
|
|
[[Note:] [Oliver: is this an interruption point?]]
|
|
[[Note:] [Oliver: wouldn't it make sense to have a corresponding `try_put()` method?]]
|
|
]
|
|
|
|
[heading Member function `take()`]
|
|
|
|
bool take( boost::optional< T > & va);
|
|
|
|
[variablelist
|
|
[[Effects:] [Dequeues a value from the queue. If no data is available from the
|
|
queue the fiber gets suspended until at least one new item is enqueued (return
|
|
value `true` and va contains dequeued value) or the queue gets deactivated and
|
|
the function returns `false`. Once the number of items remaining in the queue
|
|
drops below `lwm`, any fibers blocked on `put()` may resume.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [Oliver: is this an interruption point?]]
|
|
]
|
|
|
|
[heading Member function `try_take()`]
|
|
|
|
bool try_take( boost::optional< T > & va);
|
|
|
|
[variablelist
|
|
[[Effects:] [Dequeues a value from the queue. If no data can be retrieved from
|
|
the queue at this moment, the function returns `false`. Otherwise it returns
|
|
`true` and `va` contains the dequeued value.]]
|
|
[[Throws:] [Nothing.]]
|
|
[[Note:] [A return value of `false` does not distinguish between `empty()` and
|
|
`(! active())`.]]
|
|
]
|
|
|
|
[endsect]
|