INTRODUCTION
Overview
Download and Install
Documentation
Publications

REPOSITORY
Libraries

DEVELOPER
Dev Guide
Dashboard

PEOPLE
Contributors
Users

SourceForge.net Logo
Project
Download
Mailing lists

 

         
buffer.h
1 /*
2  * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
3  * http://gearbox.sf.net/
4  * Copyright (c) 2004-2010 Alex Brooks, Alexei Makarenko, Tobias Kaupp
5  *
6  * This distribution is licensed to you under the terms described in
7  * the LICENSE file included in this distribution.
8  *
9  */
10 
11 #ifndef GBXICEUTILACFR_BUFFER_H
12 #define GBXICEUTILACFR_BUFFER_H
13 
14 #include <queue>
15 #include <gbxutilacfr/exceptions.h>
16 
17 #include <IceUtil/Monitor.h>
18 #include <IceUtil/Mutex.h>
19 #include <IceUtil/Time.h>
20 
21 namespace gbxiceutilacfr {
22 
25 {
32 };
33 
44 template<class Type>
45 class Buffer : public IceUtil::Monitor<IceUtil::Mutex>
46 {
47 public:
48 
56 
57  virtual ~Buffer();
58 
64 
66  int depth() const;
67 
69  BufferType type() const;
70 
72  bool isEmpty() const;
73 
75  int size() const;
76 
78  void purge();
79 
86  void push( const Type & obj );
87 
92  void pop();
93 
100  void get( Type & obj ) const;
101 
106  void get( Type & obj, unsigned int n ) const;
107 
111  void getAndPop( Type & obj );
112 
124  int getWithTimeout( Type & obj, int timeoutMs=-1 );
125 
129  int getAndPopWithTimeout( Type & obj, int timeoutMs=-1 );
130 
131 protected:
132 
133  // The buffer itself
134  std::deque<Type> queue_;
135 
136  // Reimplement this function for non-standard types.
137  virtual void internalGet( Type & obj ) const ;
138 
139  // Reimplement this function for non-standard types.
140  virtual void internalGet( Type & obj, unsigned int n ) const ;
141 
142  // Reimplement this function for non-standard types.
143  virtual void internalPush( const Type & obj );
144 
145 private:
146 
147  // buffer depth:
148  // positive numbers to specify finite depth,
149  // negative numbers for infinite depth (memory size),
150  // zero is undefined
151  int depth_;
152 
153  // buffer type (see type definitions in BufferType enum)
154  BufferType type_;
155 
156  // internal implementation of getWithTimeout( obj, -1 );
157  void getWithInfiniteWait( Type & obj );
158 };
159 
160 
162 
163 
164 template<class Type>
166  : depth_(depth),
167  type_(type)
168 {
169  purge();
170 }
171 
172 template<class Type>
174 {
175 }
176 
177 template<class Type>
178 void Buffer<Type>::configure( int depth, BufferType type )
179 {
180  // all data is lost!
181  purge();
182 
183  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
184  depth_ = depth;
185  type_ = type;
186 }
187 
188 template<class Type>
189 int
191 {
192  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
193  return depth_;
194 }
195 
196 template<class Type>
197 BufferType
199 {
200  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
201  return type_;
202 }
203 
204 template<class Type>
206 {
207  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
208  queue_.resize(0);
209 }
210 
211 template<class Type>
213 {
214  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
215  return queue_.empty();
216 }
217 
218 template<class Type>
220 {
221  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
222  return queue_.size();
223 }
224 
225 template<class Type>
227 {
228  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
229  if ( queue_.empty() ) {
230  return;
231  }
232  // must check for empty queue above, otherwise get seg fault!
233  queue_.pop_front();
234 }
235 
236 template<class Type>
237 void Buffer<Type>::get( Type &obj ) const
238 {
239  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
240  if ( !queue_.empty() )
241  {
242  internalGet( obj );
243  }
244  else
245  {
246  throw gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty buffer." );
247  }
248 }
249 
250 template<class Type>
251 void Buffer<Type>::get( Type &obj, unsigned int n ) const
252 {
253  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
254  if ( queue_.empty() ){
255  throw gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty buffer." );
256  }
257  else if( n >= queue_.size()){
258  throw gbxutilacfr::Exception( ERROR_INFO, "index out of bounds while trying to read buffer." );
259  }
260  else{
261  internalGet( obj ,n );
262  }
263 }
264 
265 template<class Type>
266 void Buffer<Type>::getAndPop( Type &obj )
267 {
268  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
269  if ( !queue_.empty() )
270  {
271  internalGet( obj );
272  }
273  else
274  {
275  throw gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty buffer." );
276  }
277  queue_.pop_front();
278 }
279 
280 template<class Type>
281 int Buffer<Type>::getWithTimeout( Type &obj, int timeoutMs )
282 {
283  // special case: infinite wait time
284  if ( timeoutMs == -1 )
285  {
286  getWithInfiniteWait( obj );
287  return 0;
288  }
289 
290  // finite wait time
291  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
292 
293  // if already have data in the buffer, return it and get out
294  if ( !queue_.empty() )
295  {
296  internalGet( obj );
297  return 0;
298  }
299 
300  // empty buffer: figure out when to wake up
301  // notice that we are still holding the lock, so it's ok to call timedWait()
302  if ( this->timedWait( IceUtil::Time::milliSeconds( timeoutMs ) ) )
303  {
304  // someone woke us up, we are holding the lock again
305  // check new data again (could be a spurious wakeup)
306  if ( !queue_.empty() )
307  {
308  internalGet( obj );
309  return 0;
310  }
311  else {
312  // spurious wakup, don't wait again, just return
313  return 1;
314  }
315  }
316  else {
317  // wait timedout, nobody woke us up
318  return -1;
319  }
320 }
321 
322 template<class Type>
323 int Buffer<Type>::getAndPopWithTimeout( Type &obj, int timeoutMs )
324 {
325  int ret = getWithTimeout( obj, timeoutMs );
326  if ( ret==0 ) {
327  pop();
328  }
329  return ret;
330 }
331 
332 // internal utility function (waits for update infinitely)
333 template<class Type>
334 void Buffer<Type>::getWithInfiniteWait( Type &obj )
335 {
336  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
337 
338  // check the condition before and after waiting to deal with spurious wakeups
339  // (see Ice manual sec. 28.9.2)
340  while ( queue_.empty() )
341  {
342  this->wait();
343  }
344 
345  internalGet( obj );
346 }
347 
348 // NOTE: see notes on efficient notification in Ice sec. 28.9.3
349 template<class Type>
350 void Buffer<Type>::push( const Type & obj )
351 {
352  IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
353 
354  // buffer is not full, or buffer is configured to be of infinite size (at least for STL)
355  if ( (int)queue_.size() < depth_ || depth_<0 )
356  {
357  internalPush( obj );
358  }
359  else if ( type_ == BufferTypeCircular )
360  {
361  // pop the oldest entry
362  queue_.pop_front();
363  // push the new enty
364  internalPush( obj );
365  }
366  else // we have a full, non-circular buffer
367  {
368  // do nothing, the new object is lost
369  }
370 
371  // wakeup someone who's waiting for an update
372  this->notify();
373 }
374 
375 template<class Type>
376 void Buffer<Type>::internalGet( Type & obj ) const
377 {
378  obj = queue_.front();
379 }
380 
381 template<class Type>
382 void Buffer<Type>::internalGet( Type & obj, unsigned int n ) const
383 {
384  obj = queue_[n];
385 }
386 
387 template<class Type>
388 void Buffer<Type>::internalPush( const Type & obj )
389 {
390  queue_.push_back( obj );
391 }
392 
393 } // end namespace
394 
395 #endif
A thread-safe data pipe with buffer semantics.
Definition: buffer.h:45
void getAndPop(Type &obj)
Definition: buffer.h:266
Base class for all GbxUtilAcfr exceptions.
Definition: gbxutilacfr/exceptions.h:65
void pop()
Definition: buffer.h:226
int getWithTimeout(Type &obj, int timeoutMs=-1)
Definition: buffer.h:281
int depth() const
Returns buffer depth.
Definition: buffer.h:190
void configure(int depth, BufferType type=BufferTypeCircular)
Definition: buffer.h:178
void push(const Type &obj)
Definition: buffer.h:350
bool isEmpty() const
Returns FALSE if there&#39;s something in the buffer.
Definition: buffer.h:212
void purge()
Deletes all entries, makes the buffer empty.
Definition: buffer.h:205
Utility namespace (part of SICK-ACFR driver)
Definition: buffer.h:21
int size() const
Returns the number of items in the buffer.
Definition: buffer.h:219
int getAndPopWithTimeout(Type &obj, int timeoutMs=-1)
Definition: buffer.h:323
Definition: buffer.h:31
BufferType type() const
Returns buffer type.
Definition: buffer.h:198
BufferType
Buffer type defines behavior when the buffer is full
Definition: buffer.h:24
Buffer(int depth=-1, BufferType type=BufferTypeQueue)
Definition: buffer.h:165
Definition: buffer.h:28
 

Generated for GearBox by  doxygen 1.4.5