RingBuffer.h
Go to the documentation of this file.
1 // -*- C++ -*-
20 #ifndef RTC_RINGBUFFER_H
21 #define RTC_RINGBUFFER_H
22 
23 #include <vector>
24 #include <algorithm>
25 #include <iostream>
26 
27 #include <coil/TimeValue.h>
28 #include <coil/Mutex.h>
29 #include <coil/Guard.h>
30 #include <coil/Condition.h>
31 #include <coil/stringutil.h>
32 
33 #include <rtm/BufferBase.h>
34 #include <rtm/BufferStatus.h>
35 
36 #define RINGBUFFER_DEFAULT_LENGTH 8
37 
51 namespace RTC
52 {
88  template <class DataType>
89  class RingBuffer
90  : public BufferBase<DataType>
91  {
92  public:
119  : m_overwrite(true), m_readback(true),
120  m_timedwrite(false), m_timedread(false),
121  m_wtimeout(1, 0), m_rtimeout(1, 0),
122  m_length(length),
123  m_wpos(0), m_rpos(0), m_fillcount(0), m_wcount(0),
125  {
126  this->reset();
127  }
128 
144  virtual ~RingBuffer(void)
145  {
146  }
147 
187  virtual void init(const coil::Properties& prop)
188  {
189  initLength(prop);
190  initWritePolicy(prop);
191  initReadPolicy(prop);
192  }
193 
214  virtual size_t length(void) const
215  {
216  Guard guard(m_posmutex);
217  return m_length;
218  }
219 
242  virtual ReturnCode length(size_t n)
243  {
244  m_buffer.resize(n);
245  m_length = n;
246  this->reset();
247  return ::RTC::BufferStatus::BUFFER_OK; //BUFFER_OK;
248  }
249 
272  virtual ReturnCode reset()
273  {
274  Guard guard(m_posmutex);
275  m_fillcount = 0;
276  m_wcount = 0;
277  m_wpos = 0;
278  m_rpos = 0;
279  return ::RTC::BufferStatus::BUFFER_OK;
280  }
281 
282 
283 
284  //----------------------------------------------------------------------
305  virtual DataType* wptr(long int n = 0)
306  {
307  Guard guard(m_posmutex);
308  return &m_buffer[(m_wpos + n + m_length) % m_length];
309  }
310 
334  virtual ReturnCode advanceWptr(long int n = 1)
335  {
336  // n > 0 :
337  // n satisfies n <= writable elements
338  // n <= m_length - m_fillcout
339  // n < 0 : -n = n'
340  // n satisfies n'<= readable elements
341  // n'<= m_fillcount
342  // n >= - m_fillcount
343  Guard guard(m_posmutex);
344  if ((n > 0 && n > static_cast<long int>(m_length - m_fillcount)) ||
345  (n < 0 && n < static_cast<long int>(-m_fillcount)))
346  {
348  }
349 
350  m_wpos = (m_wpos + n + m_length) % m_length;
351  m_fillcount += n;
352  m_wcount += n;
353  return ::RTC::BufferStatus::BUFFER_OK;
354  }
382  virtual ReturnCode put(const DataType& value)
383  {
384  Guard guard(m_posmutex);
385  m_buffer[m_wpos] = value;
386  return ::RTC::BufferStatus::BUFFER_OK;
387  }
388 
430  virtual ReturnCode write(const DataType& value,
431  long int sec = -1, long int nsec = 0)
432  {
433  {
434  Guard guard(m_full.mutex);
435 
436  if (full())
437  {
438 
439  bool timedwrite(m_timedwrite);
440  bool overwrite(m_overwrite);
441 
442  if (!(sec < 0)) // if second arg is set -> block mode
443  {
444  timedwrite = true;
445  overwrite = false;
446  }
447 
448  if (overwrite && !timedwrite) // "overwrite" mode
449  {
450  advanceRptr();
451  }
452  else if (!overwrite && !timedwrite) // "do_nothing" mode
453  {
454  return ::RTC::BufferStatus::BUFFER_FULL;
455  }
456  else if (!overwrite && timedwrite) // "block" mode
457  {
458  if (sec < 0)
459  {
460  sec = m_wtimeout.sec();
461  nsec = m_wtimeout.usec() * 1000;
462  }
463  // true: signaled, false: timeout
464  if (!m_full.cond.wait(sec, nsec))
465  {
466  return ::RTC::BufferStatus::TIMEOUT;
467  }
468  }
469  else // unknown condition
470  {
472  }
473  }
474  }
475 
476  put(value);
477 
478  {
479  Guard eguard(m_empty.mutex);
480  if (empty())
481  {
482  // Guard eguard(m_empty.mutex);
483  advanceWptr(1);
484  m_empty.cond.signal();
485  }
486  else
487  {
488  advanceWptr(1);
489  }
490  }
491  return ::RTC::BufferStatus::BUFFER_OK;
492  }
493 
515  virtual size_t writable() const
516  {
517  Guard guard(m_posmutex);
518  return m_length - m_fillcount;
519  }
520 
540  virtual bool full(void) const
541  {
542  Guard guard(m_posmutex);
543  return m_length == m_fillcount;
544  }
545 
546  //----------------------------------------------------------------------
567  virtual DataType* rptr(long int n = 0)
568  {
569  Guard guard(m_posmutex);
570  return &(m_buffer[(m_rpos + n + m_length) % m_length]);
571  }
572 
594  virtual ReturnCode advanceRptr(long int n = 1)
595  {
596  // n > 0 :
597  // n satisfies n <= readable elements
598  // n <= m_fillcout
599  // n < 0 : -n = n'
600  // n satisfies n'<= m_length - m_fillcount
601  // n >= m_fillcount - m_length
602  Guard guard(m_posmutex);
603  if ((n > 0 && n > static_cast<long int>(m_fillcount)) ||
604  (n < 0 && n < static_cast<long int>(m_fillcount - m_length)))
605  {
607  }
608 
609  m_rpos = (m_rpos + n + m_length) % m_length;
610  m_fillcount -= n;
611  return ::RTC::BufferStatus::BUFFER_OK;
612  }
613 
638  virtual ReturnCode get(DataType& value)
639  {
640  Guard gaurd(m_posmutex);
641  value = m_buffer[m_rpos];
642  return ::RTC::BufferStatus::BUFFER_OK;
643  }
644 
645 
663  virtual DataType& get()
664  {
665  Guard gaurd(m_posmutex);
666  return m_buffer[m_rpos];
667  }
668 
669 
711  virtual ReturnCode read(DataType& value,
712  long int sec = -1, long int nsec = 0)
713  {
714  {
715  Guard gaurd(m_empty.mutex);
716 
717  if (empty())
718  {
719  bool timedread(m_timedread);
720  bool readback(m_readback);
721 
722  if (!(sec < 0)) // if second arg is set -> block mode
723  {
724  timedread = true;
725  readback = false;
726  sec = m_rtimeout.sec();
727  nsec = m_rtimeout.usec() * 1000;
728  }
729 
730  if (readback && !timedread) // "readback" mode
731  {
732  if (!(m_wcount > 0))
733  {
734  return ::RTC::BufferStatus::BUFFER_EMPTY;
735  }
736  advanceRptr(-1);
737  }
738  else if (!readback && !timedread) // "do_nothing" mode
739  {
740  return ::RTC::BufferStatus::BUFFER_EMPTY;
741  }
742  else if (!readback && timedread) // "block" mode
743  {
744  if (sec < 0)
745  {
746  sec = m_rtimeout.sec();
747  nsec = m_rtimeout.usec() * 1000;
748  }
749  // true: signaled, false: timeout
750  if (!m_empty.cond.wait(sec, nsec))
751  {
752  return ::RTC::BufferStatus::TIMEOUT;
753  }
754  }
755  else // unknown condition
756  {
758  }
759  }
760  }
761 
762  get(value);
763 
764  {
765  Guard fguard(m_full.mutex);
766  if (full())
767  {
768  // Guard fguard(m_full.mutex);
769  advanceRptr(1);
770  m_full.cond.signal();
771  }
772  else
773  {
774  advanceRptr(1);
775  }
776  }
777  return ::RTC::BufferStatus::BUFFER_OK;
778  }
779 
804  virtual size_t readable() const
805  {
806  Guard guard(m_posmutex);
807  return m_fillcount;
808  }
809 
829  virtual bool empty(void) const
830  {
831  Guard guard(m_posmutex);
832  return m_fillcount == 0;
833  }
834 
835  private:
836  inline void initLength(const coil::Properties& prop)
837  {
838  if (!prop["length"].empty())
839  {
840  size_t n;
841  if (coil::stringTo(n, prop["length"].c_str()))
842  {
843  if (n > 0)
844  {
845  this->length(n);
846  }
847  }
848  }
849  }
850 
852  {
853  std::string policy(prop["write.full_policy"]);
854  coil::normalize(policy);
855  if (policy == "overwrite")
856  {
857  m_overwrite = true;
858  m_timedwrite = false;
859  }
860  else if (policy == "do_nothing")
861  {
862  m_overwrite = false;
863  m_timedwrite = false;
864  }
865  else if (policy == "block")
866  {
867  m_overwrite = false;
868  m_timedwrite = true;
869 
870  double tm;
871  if (coil::stringTo(tm, prop["write.timeout"].c_str()))
872  {
873  if (!(tm < 0))
874  {
875  m_wtimeout = tm;
876  }
877  }
878  }
879  }
880 
882  {
883  std::string policy(prop["read.empty_policy"]);
884  if (policy == "readback")
885  {
886  m_readback = true;
887  m_timedread = false;
888  }
889  else if (policy == "do_nothing")
890  {
891  m_readback = false;
892  m_timedread = false;
893  }
894  else if (policy == "block")
895  {
896  m_readback = false;
897  m_timedread = true;
898  double tm;
899  if (coil::stringTo(tm, prop["read.timeout"].c_str()))
900  {
901  m_rtimeout = tm;
902  }
903  }
904  }
905 
906  private:
915 
924 
941 
950 
959 
967  size_t m_length;
968 
976  size_t m_wpos;
977 
985  size_t m_rpos;
986 
994  size_t m_fillcount;
995 
1003  size_t m_wcount;
1004 
1012  std::vector<DataType> m_buffer;
1013 
1021  struct condition
1022  {
1026  };
1027 
1036 
1045 
1054  };
1055 }; // namespace RTC
1056 
1057 #endif // RTC_RINGBUFFER_H
bool m_overwrite
Overwrite flag.
Definition: RingBuffer.h:914
coil::Mutex m_posmutex
mutex for position variable
Definition: RingBuffer.h:1035
size_t m_length
Buffer length.
Definition: RingBuffer.h:967
void initReadPolicy(const coil::Properties &prop)
Definition: RingBuffer.h:881
void initLength(const coil::Properties &prop)
Definition: RingBuffer.h:836
std::string normalize(std::string &str)
Erase the head/tail blank and replace upper case to lower case.
Definition: stringutil.cpp:308
RT-Component.
bool m_timedread
Timedread flag.
Definition: RingBuffer.h:940
virtual DataType * rptr(long int n=0)
Get the buffer length.
Definition: RingBuffer.h:567
virtual ~RingBuffer(void)
Virtual destractor.
Definition: RingBuffer.h:144
virtual ReturnCode read(DataType &value, long int sec=-1, long int nsec=0)
Readout data from the buffer.
Definition: RingBuffer.h:711
bool stringTo(To &val, const char *str)
Convert the given std::string to object.
Definition: stringutil.h:597
virtual ReturnCode length(size_t n)
Get the buffer length.
Definition: RingBuffer.h:242
Mutex class.
virtual bool full(void) const
Check on whether the buffer is full.
Definition: RingBuffer.h:540
std::vector< DataType > m_buffer
baffer array
Definition: RingBuffer.h:1012
#define RINGBUFFER_DEFAULT_LENGTH
Definition: RingBuffer.h:36
virtual void init(const coil::Properties &prop)
Set the buffer.
Definition: RingBuffer.h:187
virtual DataType * wptr(long int n=0)
Get the buffer length.
Definition: RingBuffer.h:305
Enum
DataPortStatus return codes.
Definition: BufferStatus.h:84
TimeValue class.
Definition: TimeValue.h:40
virtual ReturnCode reset()
Get the buffer length.
Definition: RingBuffer.h:272
RingBuffer(long int length=RINGBUFFER_DEFAULT_LENGTH)
Constructor.
Definition: RingBuffer.h:118
coil::TimeValue m_rtimeout
Timeout time of reading.
Definition: RingBuffer.h:958
coil::Condition< coil::Mutex > cond
Definition: RingBuffer.h:1024
#define BUFFERSTATUS_ENUM
Importing RTC::BufferStatus macro.
Definition: BufferStatus.h:157
BUFFERSTATUS_ENUM typedef coil::Guard< coil::Mutex > Guard
Definition: RingBuffer.h:94
bool m_readback
Readback flag.
Definition: RingBuffer.h:923
coil::TimeValue m_wtimeout
Timeout time for writing.
Definition: RingBuffer.h:949
Buffer status enum definition.
virtual ReturnCode advanceWptr(long int n=1)
Get the buffer length.
Definition: RingBuffer.h:334
virtual bool empty(void) const
Check on whether the buffer is empty.
Definition: RingBuffer.h:829
virtual size_t writable() const
Write data into the buffer.
Definition: RingBuffer.h:515
virtual size_t readable() const
Write data into the buffer.
Definition: RingBuffer.h:804
Buffer abstract class.
void initWritePolicy(const coil::Properties &prop)
Definition: RingBuffer.h:851
virtual ReturnCode write(const DataType &value, long int sec=-1, long int nsec=0)
Write data into the buffer.
Definition: RingBuffer.h:430
prop
Organization::get_organization_property ();.
virtual ReturnCode advanceRptr(long int n=1)
Get the buffer length.
Definition: RingBuffer.h:594
condition m_empty
empty condition variable
Definition: RingBuffer.h:1044
Class represents a set of properties.
Definition: Properties.h:101
long int sec() const
Get value of second time scale.
Definition: TimeValue.h:110
size_t m_wpos
pointer to write
Definition: RingBuffer.h:976
struct for condition variable
Definition: RingBuffer.h:1021
long int usec() const
Get value of micro second time scale.
Definition: TimeValue.h:131
bool m_timedwrite
Timedwrite flag.
Definition: RingBuffer.h:932
virtual ReturnCode put(const DataType &value)
Write data into the buffer.
Definition: RingBuffer.h:382
size_t m_rpos
poitner to read
Definition: RingBuffer.h:985
size_t m_wcount
Counter for writing.
Definition: RingBuffer.h:1003
BufferBase abstract class.
Definition: BufferBase.h:104
virtual size_t length(void) const
Get the buffer length.
Definition: RingBuffer.h:214
size_t m_fillcount
Fill count.
Definition: RingBuffer.h:994
condition m_full
full condition variable
Definition: RingBuffer.h:1053


openrtm_aist
Author(s): Noriaki Ando
autogenerated on Mon Feb 28 2022 23:00:44