20#ifndef RTC_RINGBUFFER_H
21#define RTC_RINGBUFFER_H
24#include <condition_variable>
25#include <coil/stringutil.h>
35#define RINGBUFFER_DEFAULT_LENGTH 8
87 template <
class DataType>
116 : m_length(
length), m_buffer(m_length)
177 void init(
const coil::Properties& prop)
override
180 initWritePolicy(prop);
181 initReadPolicy(prop);
206 std::lock_guard<std::mutex> guard(m_posmutex);
262 std::lock_guard<std::mutex> guard(m_posmutex);
293 DataType*
wptr(
long int n = 0)
override
295 std::lock_guard<std::mutex> guard(m_posmutex);
296 return &m_buffer[(m_wpos + n + m_length) % m_length];
326 bool lock_ = (unlock_enable && n > 0);
329 m_empty.mutex.lock();
340 std::lock_guard<std::mutex> guard(m_posmutex);
341 if ((n > 0 && n >
static_cast<long int>(m_length) -
static_cast<long int>(m_fillcount)) ||
342 (n < 0 && n < -
static_cast<long int>(m_fillcount)))
346 m_empty.mutex.unlock();
351 m_wpos = (m_wpos + n + m_length) % m_length;
360 m_empty.cond.notify_one();
362 m_empty.mutex.unlock();
396 std::lock_guard<std::mutex> guard(m_posmutex);
397 m_buffer[m_wpos] = value;
442 std::chrono::nanoseconds timeout
443 = std::chrono::nanoseconds(-1))
override
446 std::unique_lock<std::mutex> guard(m_full.mutex);
451 bool timedwrite(m_timedwrite);
452 bool overwrite(m_overwrite);
454 if (timeout >= std::chrono::seconds::zero())
460 if (overwrite && !timedwrite)
464 else if (!overwrite && !timedwrite)
468 else if (!overwrite && timedwrite)
470 if (timeout < std::chrono::seconds::zero())
472 timeout = m_wtimeout;
474 if (std::cv_status::timeout == m_empty.cond.wait_for(guard, timeout))
517 std::lock_guard<std::mutex> guard(m_posmutex);
518 return m_length - m_fillcount;
542 std::lock_guard<std::mutex> guard(m_posmutex);
543 return m_length == m_fillcount;
567 DataType*
rptr(
long int n = 0)
override
569 std::lock_guard<std::mutex> guard(m_posmutex);
570 return &(m_buffer[(m_rpos + n + m_length) % m_length]);
598 bool lock_ = (unlock_enable && n > 0);
611 std::lock_guard<std::mutex> guard(m_posmutex);
612 if ((n > 0 && n >
static_cast<long int>(m_fillcount)) ||
613 (n < 0 && n <
static_cast<long int>(m_fillcount) -
static_cast<long int>(m_length)))
617 m_full.mutex.unlock();
622 m_rpos = (m_rpos + n + m_length) % m_length;
630 m_full.cond.notify_one();
632 m_full.mutex.unlock();
664 std::lock_guard<std::mutex> guard(m_posmutex);
665 value = m_buffer[m_rpos];
689 std::lock_guard<std::mutex> guard(m_posmutex);
690 return m_buffer[m_rpos];
735 std::chrono::nanoseconds timeout
736 = std::chrono::nanoseconds(-1))
override
739 std::unique_lock<std::mutex> guard(m_empty.mutex);
743 bool timedread(m_timedread);
744 bool readback(m_readback);
746 if (timeout >= std::chrono::seconds::zero())
750 timeout = m_rtimeout;
753 if (readback && !timedread)
761 else if (!readback && !timedread)
765 else if (!readback && timedread)
767 if (timeout < std::chrono::seconds::zero())
769 timeout = m_rtimeout;
771 if (std::cv_status::timeout == m_empty.cond.wait_for(guard, timeout))
816 std::lock_guard<std::mutex> guard(m_posmutex);
841 std::lock_guard<std::mutex> guard(m_posmutex);
842 return m_fillcount == 0;
846 void initLength(
const coil::Properties& prop)
848 if (!prop[
"length"].
empty())
851 if (coil::stringTo(n, prop[
"length"].c_str()))
861 void initWritePolicy(
const coil::Properties& prop)
863 std::string policy(coil::normalize(prop[
"write.full_policy"]));
864 if (policy ==
"overwrite")
867 m_timedwrite =
false;
869 else if (policy ==
"do_nothing")
872 m_timedwrite =
false;
874 else if (policy ==
"block")
879 std::chrono::nanoseconds tm;
880 if (coil::stringTo(tm, prop[
"write.timeout"].c_str())
881 && !(tm < std::chrono::seconds::zero()))
888 void initReadPolicy(
const coil::Properties& prop)
890 std::string policy(prop[
"read.empty_policy"]);
891 if (policy ==
"readback")
896 else if (policy ==
"do_nothing")
901 else if (policy ==
"block")
905 std::chrono::nanoseconds tm;
906 if (coil::stringTo(tm, prop[
"read.timeout"].c_str()))
921 bool m_overwrite{
true};
930 bool m_readback{
true};
939 bool m_timedwrite{
false};
947 bool m_timedread{
false};
956 std::chrono::nanoseconds m_wtimeout{std::chrono::seconds(1)};
965 std::chrono::nanoseconds m_rtimeout{std::chrono::seconds(1)};
1001 size_t m_fillcount{0};
1019 std::vector<DataType> m_buffer;
1031 std::condition_variable cond;
1042 mutable std::mutex m_posmutex;
Buffer status enum definition.
#define RINGBUFFER_DEFAULT_LENGTH
Definition RingBuffer.h:35
BufferBase abstract class.
Definition BufferBase.h:106
Ring buffer implementation class.
Definition RingBuffer.h:90
DataType * rptr(long int n=0) override
Get the buffer length.
Definition RingBuffer.h:567
size_t writable() const override
Write data into the buffer.
Definition RingBuffer.h:515
BufferStatus write(const DataType &value, std::chrono::nanoseconds timeout=std::chrono::nanoseconds(-1)) override
Write data into the buffer.
Definition RingBuffer.h:441
size_t readable() const override
Write data into the buffer.
Definition RingBuffer.h:814
BufferStatus advanceWptr(long int n=1, bool unlock_enable=true) override
Get the buffer length.
Definition RingBuffer.h:323
size_t length() const override
Get the buffer length.
Definition RingBuffer.h:204
RingBuffer(long int length=RINGBUFFER_DEFAULT_LENGTH)
Constructor.
Definition RingBuffer.h:115
BufferStatus advanceRptr(long int n=1, bool unlock_enable=true) override
Get the buffer length.
Definition RingBuffer.h:595
BufferStatus reset() override
Get the buffer length.
Definition RingBuffer.h:260
BufferStatus length(size_t n) override
Get the buffer length.
Definition RingBuffer.h:230
DataType * wptr(long int n=0) override
Get the buffer length.
Definition RingBuffer.h:293
BufferStatus get(DataType &value) override
Write data into the buffer.
Definition RingBuffer.h:662
DataType & get() override
Reading data from the buffer.
Definition RingBuffer.h:687
~RingBuffer() override
Virtual destractor.
bool full() const override
Check on whether the buffer is full.
Definition RingBuffer.h:540
BufferStatus put(const DataType &value) override
Write data into the buffer.
Definition RingBuffer.h:394
bool empty() const override
Check on whether the buffer is empty.
Definition RingBuffer.h:839
BufferStatus read(DataType &value, std::chrono::nanoseconds timeout=std::chrono::nanoseconds(-1)) override
Readout data from the buffer.
Definition RingBuffer.h:734
void init(const coil::Properties &prop) override
Definition RingBuffer.h:177
BufferStatus
DataPortStatus return codes.
Definition BufferStatus.h:57