Orocos Real-Time Toolkit  2.8.3
BufferLocked.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  tag: Peter Soetens Wed Jan 18 14:11:39 CET 2006 BufferLocked.hpp
3 
4  BufferLocked.hpp - description
5  -------------------
6  begin : Wed January 18 2006
7  copyright : (C) 2006 Peter Soetens
8  email : peter.soetens@mech.kuleuven.be
9 
10  ***************************************************************************
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU General Public *
13  * License as published by the Free Software Foundation; *
14  * version 2 of the License. *
15  * *
16  * As a special exception, you may use this file as part of a free *
17  * software library without restriction. Specifically, if other files *
18  * instantiate templates or use macros or inline functions from this *
19  * file, or you compile this file and link it with other files to *
20  * produce an executable, this file does not by itself cause the *
21  * resulting executable to be covered by the GNU General Public *
22  * License. This exception does not however invalidate any other *
23  * reasons why the executable file might be covered by the GNU General *
24  * Public License. *
25  * *
26  * This library is distributed in the hope that it will be useful, *
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
29  * Lesser General Public License for more details. *
30  * *
31  * You should have received a copy of the GNU General Public *
32  * License along with this library; if not, write to the Free Software *
33  * Foundation, Inc., 59 Temple Place, *
34  * Suite 330, Boston, MA 02111-1307 USA *
35  * *
36  ***************************************************************************/
37 
38 
39 
40 
41 
42 #ifndef ORO_CORELIB_BUFFER_LOCKED_HPP
43 #define ORO_CORELIB_BUFFER_LOCKED_HPP
44 
45 #include "../os/Mutex.hpp"
46 #include "../os/MutexLock.hpp"
47 #include "BufferInterface.hpp"
48 #include <deque>
49 
50 namespace RTT
51 { namespace base {
52 
53 
60  template<class T>
62  :public BufferInterface<T>
63  {
64  public:
65 
69  typedef T value_t;
70 
77  BufferLocked( size_type size, const T& initial_value = T(), bool circular = false )
78  : cap(size), buf(), mcircular(circular), droppedSamples(0)
79  {
80  data_sample(initial_value);
81  }
82 
83  virtual void data_sample( const T& sample )
84  {
85  buf.resize(cap, sample);
86  buf.resize(0);
87  lastSample = sample;
88  }
89 
90  virtual T data_sample() const
91  {
92  return lastSample;
93  }
94 
99 
100  bool Push( param_t item )
101  {
102  os::MutexLock locker(lock);
103  if ( cap == (size_type)buf.size() ) {
104  //buffer is full, we either overwrite a sample, or drop the given one
105  droppedSamples++;
106  if (!mcircular)
107  {
108  return false;
109  }
110  else
111  buf.pop_front();
112  }
113  buf.push_back( item );
114  return true;
115  }
116 
117  size_type Push(const std::vector<T>& items)
118  {
119  os::MutexLock locker(lock);
120  typename std::vector<T>::const_iterator itl( items.begin() );
121  if (mcircular && (size_type)items.size() >= cap ) {
122  // clear out current data and reset iterator to first element we're going to take.
123  buf.clear();
124  //note the ignored samples are added below to the dropped samples.
125  droppedSamples += cap;
126  itl = items.begin() + ( items.size() - cap );
127  } else if ( mcircular && (size_type)(buf.size() + items.size()) > cap) {
128  // drop excess elements from front
129  assert( (size_type)items.size() < cap );
130  while ( (size_type)(buf.size() + items.size()) > cap )
131  {
132  droppedSamples++;
133  buf.pop_front();
134  }
135  // itl still points at first element of items.
136  }
137  while ( ((size_type)buf.size() != cap) && (itl != items.end()) ) {
138  buf.push_back( *itl );
139  ++itl;
140  }
141  // this is in any case the number of elements taken from items.
142  size_type writtenSamples = itl - items.begin();
143 
144  if (mcircular)
145  assert( writtenSamples == (size_type)items.size() );
146 
147  droppedSamples += items.size() - writtenSamples;
148 
149  return writtenSamples;
150  }
151  bool Pop( reference_t item )
152  {
153  os::MutexLock locker(lock);
154  if ( buf.empty() ) {
155  return false;
156  }
157  item = buf.front();
158  buf.pop_front();
159  return true;
160  }
161 
162  size_type Pop(std::vector<T>& items )
163  {
164  os::MutexLock locker(lock);
165  int quant = 0;
166  items.clear();
167  while ( !buf.empty() ) {
168  items.push_back( buf.front() );
169  buf.pop_front();
170  ++quant;
171  }
172  return quant;
173  }
174 
175  value_t* PopWithoutRelease()
176  {
177  os::MutexLock locker(lock);
178  if(buf.empty())
179  return 0;
180 
181  //note we need to copy the sample, as
182  //front is not garanteed to be valid after
183  //any other operation on the deque
184  lastSample = buf.front();
185  buf.pop_front();
186  return &lastSample;
187  }
188 
189  void Release(value_t *item)
190  {
191  //we do not need to release any memory, but we can check
192  //if the other side messed up
193  assert(item == &lastSample && "Wrong pointer given back to buffer");
194  }
195 
196  size_type capacity() const {
197  os::MutexLock locker(lock);
198  return cap;
199  }
200 
201  size_type size() const {
202  os::MutexLock locker(lock);
203  return buf.size();
204  }
205 
206  void clear() {
207  os::MutexLock locker(lock);
208  buf.clear();
209  }
210 
211  bool empty() const {
212  os::MutexLock locker(lock);
213  return buf.empty();
214  }
215 
216  bool full() const {
217  os::MutexLock locker(lock);
218  return (size_type)buf.size() == cap;
219  }
220 
221  size_type dropped() const
222  {
223  return droppedSamples;
224  }
225  private:
226  size_type cap;
227  std::deque<T> buf;
228  value_t lastSample;
229  mutable os::Mutex lock;
230  const bool mcircular;
231  size_type droppedSamples;
232  };
233 }}
234 
235 #endif // BUFFERSIMPLE_HPP
virtual T data_sample() const
Reads back a data sample.
boost::call_traits< T >::reference reference_t
BufferLocked(size_type size, const T &initial_value=T(), bool circular=false)
Create a buffer of size size, with preallocated data storage.
A Buffer is an object which is used to store (Push) and retrieve (Pop) values from.
virtual void data_sample(const T &sample)
Initializes this buffer with a data sample, such that for dynamical allocated types T...
boost::call_traits< T >::param_type param_t
size_type dropped() const
Returns the number of dropped samples, because the buffer was full.
void Release(value_t *item)
Releases the pointer.
value_t * PopWithoutRelease()
Returns a pointer to the first element in the buffer.
bool Push(param_t item)
Write a single value to the buffer.
size_type Push(const std::vector< T > &items)
Write a sequence of values to the buffer.
bool empty() const
Check if this buffer is empty.
BufferBase::size_type size_type
BufferInterface< T >::size_type size_type
BufferInterface< T >::param_t param_t
bool full() const
Check if this buffer is full.
BufferInterface< T >::reference_t reference_t
size_type size() const
Returns the actual number of items that are stored in the buffer.
Implements a very simple blocking thread-safe buffer, using mutexes (locks).
~BufferLocked()
Destructor.
void clear()
Clears all contents of this buffer.
size_type capacity() const
Returns the maximum number of items that can be stored in the buffer.
bool Pop(reference_t item)
Read the oldest value from the buffer.
An object oriented wrapper around a non recursive mutex.
Definition: Mutex.hpp:82
Contains TaskContext, Activity, OperationCaller, Operation, Property, InputPort, OutputPort, Attribute.
Definition: Activity.cpp:51
size_type Pop(std::vector< T > &items)
Read the whole buffer.
MutexLock is a scope based Monitor, protecting critical sections with a Mutex object through locking ...
Definition: MutexLock.hpp:51