27
27
*
28
28
* In particular, @c wait_queue:
29
29
*
30
- * - Has been tested with Martin Moene's @c ring_span library for the internal container.
31
- * A @c ring_span is traditionally known as a "ring buffer" or "circular buffer". This
32
- * implies that the @c wait_queue can be used in environments where dynamic memory
33
- * management (heap) is not allowed or is problematic. In particular, no heap memory is
34
- * directly allocated within the @c wait_queue object.
30
+ * - Has been tested with Martin Moene's @c ring_span library for the internal container,
31
+ * as well as Justin Masiulis' @c circular_buffer library. A "ring buffer" or
32
+ * "circular buffer" uses a fixed size container and implies that the @c wait_queue can
33
+ * be used in environments where dynamic memory management (heap) is not allowed or is
34
+ * problematic. In particular, no heap memory will be directly allocated within the
35
+ * @c wait_queue object. A @c ring_span is a view on a container object instead of
36
+ * directly owning the container, so there are differences in construction and
37
+ * container management.
35
38
*
36
39
* - Does not throw or catch exceptions anywhere in its code base. If a value being pushed
37
40
* on to the queue throws an exception, it can be caught by the pushing code (or higher
102
105
* @code
103
106
* const int sz = 20;
104
107
* int buf[sz];
105
- * chops::wait_queue<int, nonstd::ring_span<int> > wq(buf+0, buf+sz);
108
+ * chops::wait_queue<int, nonstd::ring_span<int> >
109
+ * wq { nonstd::ring_span<int> { buf+0, buf+sz } };
106
110
* // push and pop same as code with default container
107
111
* @endcode
108
112
*
109
113
* The container type must support the following (depending on which
110
- * methods are called): default construction, construction from a
111
- * begin and end iterator, construction with an initial size,
114
+ * methods are called): default construction, construction with an initial size,
112
115
* @c push_back (preferably overloaded for both copy and move),
113
116
* @c emplace_back (with a template parameter pack), @c front, @c pop_front,
114
117
* @c empty, and @c size. The container must also have a @c size_type
134
137
* @c circular_buffer then the default constructor for @c wait_queue cannot be used
135
138
* (since it would result in a container with an empty capacity).
136
139
*
140
+ * Thanks go to Lou Langholtz for adding DBC (Design by Contract) assertions.
137
141
*
138
- * @authors Cliff Green, Anthony Williams
142
+ * @authors Cliff Green, Lou Langholtz, Anthony Williams
139
143
*
140
144
* @copyright (c) 2017-2024 by Cliff Green
141
145
*
@@ -186,9 +190,9 @@ class wait_queue {
186
190
* anything, so a different @c wait_queue constructor must be used if
187
191
* instantiated with a @c boost @c circular_buffer.
188
192
*
189
- * @post @c empty returns true.
193
+ * @post @c empty returns @c true.
190
194
* @post @c size returns 0.
191
- * @post @c stop_requested return false.
195
+ * @post @c stop_requested returns @c false.
192
196
*/
193
197
wait_queue ()
194
198
// noexcept(std::is_nothrow_constructible<Container>::value)
@@ -204,7 +208,7 @@ class wait_queue {
204
208
* @param stop_tok A @c std::stop_token which can be used to shutdown @c wait_queue
205
209
* processing.
206
210
*
207
- * @post @c empty returns true.
211
+ * @post @c empty returns @c true.
208
212
* @post @c size returns 0.
209
213
*/
210
214
wait_queue (std::stop_token stop_tok)
@@ -215,55 +219,52 @@ class wait_queue {
215
219
}
216
220
217
221
/* *
218
- * @brief Construct a @c wait_queue with an iterator range for the container.
222
+ * @brief Construct a @c wait_queue by moving in an already constructed
223
+ * container.
219
224
*
220
- * Construct the container (or container view) with an iterator range. Whether
221
- * element copies are performed depends on the container type. Most container
222
- * types copy initial elements as defined by the range and the initial size is
223
- * set accordingly. A @c ring_span, however, uses the range distance to define
224
- * a capacity and sets the initial size to zero.
225
+ * This constructor allows a container view to be used for the @c wait_queue
226
+ * container. Typically a container view is initialized with an underlying
227
+ * object, for example a statically allocated array. This allows @c wait_queue
228
+ * to be used where dynamic memory is not allowed.
229
+ *
230
+ * This constructor also allows arbitrary initialization of the data inside
231
+ * the container before it is managed by the @c wait_queue.
225
232
*
226
233
* An internal @c std::stop_source is used to provide a @c std::stop_token for
227
234
* coordinating shutdown.
228
235
*
229
- * @note This is the only constructor that can be used with a @c ring_span
230
- * container type.
231
- *
232
- * @param beg Beginning iterator.
233
- *
234
- * @param end Ending iterator.
236
+ * @param container Container object to be moved from (or copied from if not
237
+ * movable).
235
238
*
236
- * @post @c empty returns true if @c beg equals @c end otherwise returns false.
239
+ * @post @c empty returns @c true if @c beg equals @c end otherwise returns @c false.
237
240
* @post @c size returns the distance between @c beg and @c end parameters.
238
241
*/
239
- template <typename Iter>
240
- wait_queue (Iter beg, Iter end)
241
- // noexcept(std::is_nothrow_constructible<Container, Iter, Iter>::value)
242
+ wait_queue (Container&& container)
243
+ // noexcept(std::is_ something movable or maybe copyable )
242
244
: m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
243
- m_data_queue (beg, end ) {
244
- assert (empty () == (beg == end));
245
- assert ((size () == size_type (0 )) == (beg == end)); // std::distance constrains beg, end.
245
+ m_data_queue (std::move(container) ) {
246
+ // assert(empty() == (beg == end));
247
+ // assert((size() == size_type(0)) == (beg == end)); // std::distance constrains beg, end.
246
248
}
247
249
248
250
/* *
249
- * @brief Construct a @c wait_queue with an iterator range and a @c std::stop_token.
251
+ * This constructor allows a container view to be used for the @c wait_queue
252
+ * container. It also takes a @c std::stop_token for external shutdown.
250
253
*
251
254
* @param stop_tok A @c std::stop_token which can be used to shutdown @c wait_queue
252
255
* processing.
253
256
*
254
- * @param beg Beginning iterator.
255
- *
256
- * @param end Ending iterator.
257
+ * @param container Container object to be moved from (or copied from if not
258
+ * movable).
257
259
*
258
- * @post @c empty returns true if @c beg equals @c end otherwise returns false.
260
+ * @post @c empty returns @c true if @c beg equals @c end otherwise returns @c false.
259
261
* @post @c size returns the distance between @c beg and @c end parameters.
260
262
*/
261
- template <typename Iter>
262
- wait_queue (std::stop_token stop_tok, Iter beg, Iter end)
263
+ wait_queue (std::stop_token stop_tok, Container&& container)
263
264
// noexcept(std::is_nothrow_constructible<Container, Iter, Iter>::value)
264
- : m_stop_tok(stop_tok), m_data_queue(beg, end ) {
265
- assert (empty () == (beg == end));
266
- assert ((size () == size_type (0 )) == (beg == end)); // std::distance constrains beg, end.
265
+ : m_stop_tok(stop_tok), m_data_queue(std::move(container) ) {
266
+ // assert(empty() == (beg == end));
267
+ // assert((size() == size_type(0)) == (beg == end)); // std::distance constrains beg, end.
267
268
}
268
269
269
270
/* *
@@ -285,7 +286,7 @@ class wait_queue {
285
286
*
286
287
* @param sz Capacity or initial size, depending on container type.
287
288
*
288
- * @post If @c sz is 0 @c empty returns true, else behavior depends on container used.
289
+ * @post If @c sz is 0 @c empty returns @c true, else behavior depends on container used.
289
290
* @post @c size returns 0 or @c sz depending on container used.
290
291
*/
291
292
wait_queue (size_type sz)
@@ -305,7 +306,7 @@ class wait_queue {
305
306
*
306
307
* @param sz Capacity or initial size, depending on container type.
307
308
*
308
- * @post If @c sz is 0 @c empty returns true, else behavior depends on container used.
309
+ * @post If @c sz is 0 @c empty returns @c true, else behavior depends on container used.
309
310
* @post @c size returns 0 or @c sz depending on container used.
310
311
*/
311
312
wait_queue (std::stop_token stop_tok, size_type sz)
@@ -360,7 +361,7 @@ class wait_queue {
360
361
* @return @c true if successful, @c false if the @c wait_queue has been
361
362
* requested to stop.
362
363
*
363
- * @post If @c true is returned and @c empty is false, one of any threads waiting for a
364
+ * @post If @c true is returned and @c empty is @c false, one of any threads waiting for a
364
365
* value will be unblocked.
365
366
*/
366
367
auto push (const T& val) /* noexcept(std::is_nothrow_copy_constructible<T>::value) */
@@ -382,7 +383,7 @@ class wait_queue {
382
383
* This method has the same semantics as the other @c push, except that the value will
383
384
* be moved (if possible) instead of copied.
384
385
*
385
- * @post If @c true is returned and @c empty is false, one of any threads waiting for a
386
+ * @post If @c true is returned and @c empty is @c false, one of any threads waiting for a
386
387
* value will be unblocked.
387
388
*/
388
389
auto push (T&& val) /* noexcept(std::is_nothrow_move_constructible<T>::value) */
@@ -411,7 +412,7 @@ class wait_queue {
411
412
* @return @c true if successful, @c false if the @c wait_queue is has been requested
412
413
* to stop.
413
414
*
414
- * @post If @c true is returned and @c empty is false, one of any threads waiting for a
415
+ * @post If @c true is returned and @c empty is @c false, one of any threads waiting for a
415
416
* value will be unblocked.
416
417
*/
417
418
template <typename ... Args>
0 commit comments