summaryrefslogtreecommitdiffstats
path: root/include/jau/ringbuffer.hpp
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2021-06-19 03:49:50 +0200
committerSven Gothel <[email protected]>2021-06-19 03:49:50 +0200
commit63d20321d725308546f403bdf6e8b4a40eb5c124 (patch)
tree834ef3ab93182eefea540a572e9c1b836db5190b /include/jau/ringbuffer.hpp
parent6ee45fee50c1704ce6685f344283d208cf8f1031 (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.hpp59
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). */