E5FD Some DBC associated changes for consideration · connectivecpp/wait-queue@0a96c07 · GitHub
[go: up one dir, main page]

Skip to content

Commit 0a96c07

Browse files
Some DBC associated changes for consideration
1 parent f84fb58 commit 0a96c07

File tree

1 file changed

+73
-13
lines changed

1 file changed

+73
-13
lines changed

include/queue/wait_queue.hpp

Lines changed: 73 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@
147147
#ifndef WAIT_QUEUE_HPP_INCLUDED
148148
#define WAIT_QUEUE_HPP_INCLUDED
149149

150+
#include <cassert> // assert
150151
#include <deque>
151152
#include <mutex> // std::scoped_lock, std::mutex
152153
#include <condition_variable>
@@ -185,23 +186,35 @@ class wait_queue {
185186
* anything, so a different @c wait_queue constructor must be used if
186187
* instantiated with a @c boost @c circular_buffer.
187188
*
189+
* @post @c empty returns true.
190+
* @post @c size returns 0.
191+
* @post @c stop_requested return false.
188192
*/
189193
wait_queue()
190194
// noexcept(std::is_nothrow_constructible<Container>::value)
191-
: m_mut(), m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
192-
m_data_cond(), m_data_queue() { }
195+
: m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token())
196+
{
197+
assert(empty());
198+
assert(size() == size_type(0));
199+
assert(!stop_requested());
200+
}
193201

194202
/**
195203
* @brief Construct a @c wait_queue with an externally provided @c std::stop_token.
196204
*
197205
* @param stop_tok A @c std::stop_token which can be used to shutdown @c wait_queue
198206
* processing.
199207
*
208+
* @post @c empty returns true.
209+
* @post @c size returns 0.
200210
*/
201211
wait_queue(std::stop_token stop_tok)
202212
// noexcept(std::is_nothrow_constructible<Container>::value)
203-
: m_mut(), m_stop_src(), m_stop_tok(stop_tok),
204-
m_data_cond(), m_data_queue() { }
213+
: m_stop_tok(stop_tok)
214+
{
215+
assert(empty());
216+
assert(size() == size_type(0));
217+
}
205218

206219
/**
207220
* @brief Construct a @c wait_queue with an iterator range for the container.
@@ -221,12 +234,19 @@ class wait_queue {
221234
* @param beg Beginning iterator.
222235
*
223236
* @param end Ending iterator.
237+
*
238+
* @post @c empty returns true if @c beg equals @c end otherwise returns false.
239+
* @post @c size returns the distance between @c beg and @c end parameters.
224240
*/
225241
template <typename Iter>
226242
wait_queue(Iter beg, Iter end)
227243
// noexcept(std::is_nothrow_constructible<Container, Iter, Iter>::value)
228-
: m_mut(), m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
229-
m_data_cond(), m_data_queue(beg, end) { }
244+
: m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
245+
m_data_queue(beg, end)
246+
{
247+
assert(empty() == (beg == end));
248+
assert((size() == size_type(0)) == (beg == end)); // std::distance constrains beg, end.
249+
}
230250

231251
/**
232252
* @brief Construct a @c wait_queue with an iterator range and a @c std::stop_token.
@@ -237,12 +257,18 @@ class wait_queue {
237257
* @param beg Beginning iterator.
238258
*
239259
* @param end Ending iterator.
260+
*
261+
* @post @c empty returns true if @c beg equals @c end otherwise returns false.
262+
* @post @c size returns the distance between @c beg and @c end parameters.
240263
*/
241264
template <typename Iter>
242265
wait_queue(std::stop_token stop_tok, Iter beg, Iter end)
243266
// noexcept(std::is_nothrow_constructible<Container, Iter, Iter>::value)
244-
: m_mut(), m_stop_src(), m_stop_tok(stop_tok),
245-
m_data_cond(), m_data_queue(beg, end) { }
267+
: m_stop_tok(stop_tok), m_data_queue(beg, end)
268+
{
269+
assert(empty() == (beg == end));
270+
assert((size() == size_type(0)) == (beg == end)); // std::distance constrains beg, end.
271+
}
246272

247273
/**
248274
* @brief Construct a @c wait_queue with an initial size or capacity.
@@ -263,11 +289,17 @@ class wait_queue {
263289
*
264290
* @param sz Capacity or initial size, depending on container type.
265291
*
292+
* @post If @c sz is 0 @c empty returns true, else behavior depends on container used.
293+
* @post @c size returns 0 or @c sz depending on container used.
266294
*/
267295
wait_queue(size_type sz)
268296
// noexcept(std::is_nothrow_constructible<Container, size_type>::value)
269-
: m_mut(), m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
270-
m_data_cond(), m_data_queue(sz) { }
297+
: m_stop_src(std::stop_source{}), m_stop_tok((*m_stop_src).get_token()),
298+
m_data_queue(sz)
299+
{
300+
assert((sz != size_type(0)) || empty());
301+
assert((size() == size_type(0)) || (size() == sz));
302+
}
271303

272304
/**
273305
* @brief Construct a @c wait_queue with an initial size or capacity along
@@ -278,11 +310,16 @@ class wait_queue {
278310
*
279311
* @param sz Capacity or initial size, depending on container type.
280312
*
313+
* @post If @c sz is 0 @c empty returns true, else behavior depends on container used.
314+
* @post @c size returns 0 or @c sz depending on container used.
281315
*/
282316
wait_queue(std::stop_token stop_tok, size_type sz)
283317
// noexcept(std::is_nothrow_constructible<Container, size_type>::value)
284-
: m_mut(), m_stop_src(), m_stop_tok((*m_stop_src).get_token()),
285-
m_data_cond(), m_data_queue(sz) { }
318+
: m_stop_tok((*m_stop_src).get_token()), m_data_queue(sz)
319+
{
320+
assert((sz != size_type(0)) || empty());
321+
assert((size() == size_type(0)) || (size() == sz));
322+
}
286323

287324
// disallow copy or move construction of the entire object
288325
wait_queue(const wait_queue&) = delete;
@@ -307,7 +344,6 @@ class wait_queue {
307344
* @return @c true if an internal @c stop_source was used (versus a @c std::stop_token
308345
* passed in to the constructor) and the request returns @c true, @c false if an
309346
* external @c std::stop_token was passed in.
310-
*
311347
*/
312348
auto request_stop() noexcept
313349
-> bool {
@@ -329,6 +365,9 @@ class wait_queue {
329365
*
330366
* @return @c true if successful, @c false if the @c wait_queue has been
331367
* requested to stop.
368+
*
369+
* @post If @c true is returned and @c empty is false, one of any threads waiting for a
370+
* value will be unblocked.
332371
*/
333372
auto push(const T& val) /* noexcept(std::is_nothrow_copy_constructible<T>::value) */
334373
-> bool {
@@ -348,6 +387,9 @@ class wait_queue {
348387
*
349388
* This method has the same semantics as the other @c push, except that the value will
350389
* be moved (if possible) instead of copied.
390+
*
391+
* @post If @c true is returned and @c empty is false, one of any threads waiting for a
392+
* value will be unblocked.
351393
*/
352394
auto push(T&& val) /* noexcept(std::is_nothrow_move_constructible<T>::value) */
353395
-> bool {
@@ -374,6 +416,9 @@ class wait_queue {
374416
*
375417
* @return @c true if successful, @c false if the @c wait_queue is has been requested
376418
* to stop.
419+
*
420+
* @post If @c true is returned and @c empty is false, one of any threads waiting for a
421+
* value will be unblocked.
377422
*/
378423
template <typename ... Args>
379424
auto emplace_push(Args &&... args) /* noexcept(std::is_nothrow_constructible<T, Args...>::value)*/
@@ -399,6 +444,9 @@ class wait_queue {
399444
*
400445
* @return A value from the @c wait_queue (if non-empty). If the @c std::optional is empty,
401446
* the @c wait_queue has been requested to be stopped.
447+
*
448+
* @post If a non empty value is returned, until a push function is called, @c size is one
449+
* less than before this function was called.
402450
*/
403451
auto wait_and_pop() /* noexcept(std::is_nothrow_constructible<T>::value) */
404452
-> std::optional<T> {
@@ -407,8 +455,13 @@ class wait_queue {
407455
if (!m_data_cond.wait ( lk, m_stop_tok, [this] { return !m_data_queue.empty(); } )) {
408456
return std::optional<T> {}; // queue was request to stop, no data available
409457
}
458+
assert(!m_data_queue.empty());
459+
#ifndef NDEBUG
460+
const auto old_size = m_data_queue.size();
461+
#endif
410462
std::optional<T> val {std::move_if_noexcept(m_data_queue.front())}; // move construct if possible
411463
m_data_queue.pop_front();
464+
assert(m_data_queue.size() + 1u == old_size);
412465
return val;
413466

414467
}
@@ -420,6 +473,9 @@ class wait_queue {
420473
* @return A value from the @c wait_queue or an empty @c std::optional if no values are
421474
* available in the @c wait_queue or if the @c wait_queue has been requested to be
422475
* stopped .
476+
*
477+
* @post If a non empty value is returned, until a push function is called, @c size is one
478+
* less than before this function was called.
423479
*/
424480
auto try_pop() /* noexcept(std::is_nothrow_constructible<T>::value) */
425481
-> std::optional<T> {
@@ -431,8 +487,12 @@ class wait_queue {
431487
if (m_data_queue.empty()) {
432488
return std::optional<T> {};
433489
}
490+
#ifndef NDEBUG
491+
const auto old_size = m_data_queue.size();
492+
#endif
434493
std::optional<T> val {std::move_if_noexcept(m_data_queue.front())}; // move construct if possible
435494
m_data_queue.pop_front();
495+
assert(m_data_queue.size() + 1u == old_size);
436496
return val;
437497

438498
}

0 commit comments

Comments
 (0)
0