diff options
author | Sven Gothel <[email protected]> | 2021-06-19 03:49:50 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2021-06-19 03:49:50 +0200 |
commit | 63d20321d725308546f403bdf6e8b4a40eb5c124 (patch) | |
tree | 834ef3ab93182eefea540a572e9c1b836db5190b /include/jau/ringbuffer.hpp | |
parent | 6ee45fee50c1704ce6685f344283d208cf8f1031 (diff) |
ringbuffer: Add 'Size_type waitForElements(..)' and fix 'Size_type waitForFreeSlots(..)'
Both methods only take the minimum count to wait for (elements available or free slots)
and return the actual count.
Diffstat (limited to 'include/jau/ringbuffer.hpp')
-rw-r--r-- | include/jau/ringbuffer.hpp | 59 |
1 files changed, 48 insertions, 11 deletions
diff --git a/include/jau/ringbuffer.hpp b/include/jau/ringbuffer.hpp index fe18909..5ad5ebf 100644 --- a/include/jau/ringbuffer.hpp +++ b/include/jau/ringbuffer.hpp @@ -678,30 +678,67 @@ class ringbuffer { public: /** - * Blocks until at least <code>count</code> free slots become available. - * @throws InterruptedException + * Blocks until at least <code>count</code> elements have been put + * for subsequent get() and getBlocking(). + * + * @param min_count minimum number of put slots + * @param timeoutMS + * @return the number of put elements, available for get() and getBlocking() + */ + Size_type waitForElements(const Size_type min_count, const int timeoutMS) noexcept { + std::unique_lock<std::mutex> lockMultiRead(syncMultiRead); // acquire syncMultiRead, _not_ sync'ing w/ putImpl + + Size_type available = getSize(); + if( min_count > available ) { + std::unique_lock<std::mutex> lockWrite(syncWrite); // SC-DRF w/ putImpl via same lock + available = getSize(); + while( min_count > available ) { + if( 0 == timeoutMS ) { + cvWrite.wait(lockWrite); + available = getSize(); + } else { + std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); + std::cv_status s = cvWrite.wait_until(lockWrite, t0 + std::chrono::milliseconds(timeoutMS)); + available = getSize(); + if( std::cv_status::timeout == s && min_count > available ) { + return available; + } + } + } + } + return available; + } + + /** + * Blocks until at least <code>count</code> free slots become available + * for subsequent put() and putBlocking(). + * + * @param min_count minimum number of free slots + * @param timeoutMS + * @return the number of free slots, available for put() and putBlocking() */ - void waitForFreeSlots(const Size_type count, const int timeoutMS) noexcept { - std::unique_lock<std::mutex> lockMultiWrite(syncMultiRead); // utilize std::lock(r, w), allowing mixed order waiting on read/write ops + Size_type waitForFreeSlots(const Size_type min_count, const int timeoutMS) noexcept { + std::unique_lock<std::mutex> lockMultiWrite(syncMultiWrite); // acquire syncMultiWrite, _not_ sync'ing w/ getImpl Size_type available = getFreeSlots(); - if( count > available ) { - std::unique_lock<std::mutex> lockWrite(syncRead); // SC-DRF w/ getImpl via same lock + if( min_count > available ) { + std::unique_lock<std::mutex> lockRead(syncRead); // SC-DRF w/ getImpl via same lock available = getFreeSlots(); - while( count > available ) { + while( min_count > available ) { if( 0 == timeoutMS ) { - cvRead.wait(lockWrite); + cvRead.wait(lockRead); available = getFreeSlots(); } else { std::chrono::steady_clock::time_point t0 = std::chrono::steady_clock::now(); - std::cv_status s = cvRead.wait_until(lockWrite, t0 + std::chrono::milliseconds(timeoutMS)); + std::cv_status s = cvRead.wait_until(lockRead, t0 + std::chrono::milliseconds(timeoutMS)); available = getFreeSlots(); - if( std::cv_status::timeout == s && count > available ) { - return; + if( std::cv_status::timeout == s && min_count > available ) { + return available; } } } } + return available; } /** Returns a short string representation incl. size/capacity and internal r/w index (impl. dependent). */ |