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
21namespace gbxiceutilacfr {
22
33
44template<class Type>
45class Buffer : public IceUtil::Monitor<IceUtil::Mutex>
46{
47public:
48
56
57 virtual ~Buffer();
58
64
66 int depth() const;
67
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
131protected:
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
145private:
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
164template<class Type>
166 : depth_(depth),
167 type_(type)
168{
169 purge();
170}
171
172template<class Type>
173Buffer<Type>::~Buffer()
174{
175}
176
177template<class 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
188template<class Type>
189int
191{
192 IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
193 return depth_;
194}
195
196template<class Type>
199{
200 IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
201 return type_;
202}
203
204template<class Type>
206{
207 IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
208 queue_.resize(0);
209}
210
211template<class Type>
213{
214 IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
215 return queue_.empty();
216}
217
218template<class Type>
220{
221 IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
222 return queue_.size();
223}
224
225template<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
236template<class Type>
237void 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
250template<class Type>
251void 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
265template<class Type>
266void 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
280template<class Type>
281int 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
322template<class Type>
323int 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)
333template<class Type>
334void 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
349template<class Type>
350void 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
375template<class Type>
376void Buffer<Type>::internalGet( Type & obj ) const
377{
378 obj = queue_.front();
379}
380
381template<class Type>
382void Buffer<Type>::internalGet( Type & obj, unsigned int n ) const
383{
384 obj = queue_[n];
385}
386
387template<class Type>
388void Buffer<Type>::internalPush( const Type & obj )
389{
390 queue_.push_back( obj );
391}
392
393} // end namespace
394
395#endif
void purge()
Deletes all entries, makes the buffer empty.
Definition buffer.h:205
void configure(int depth, BufferType type=BufferTypeCircular)
Definition buffer.h:178
BufferType type() const
Definition buffer.h:198
Buffer(int depth=-1, BufferType type=BufferTypeQueue)
Definition buffer.h:165
int size() const
Returns the number of items in the buffer.
Definition buffer.h:219
void pop()
Definition buffer.h:226
int getAndPopWithTimeout(Type &obj, int timeoutMs=-1)
Definition buffer.h:323
void push(const Type &obj)
Definition buffer.h:350
bool isEmpty() const
Returns FALSE if there's something in the buffer.
Definition buffer.h:212
void get(Type &obj) const
Definition buffer.h:237
void getAndPop(Type &obj)
Definition buffer.h:266
int getWithTimeout(Type &obj, int timeoutMs=-1)
Definition buffer.h:281
void get(Type &obj, unsigned int n) const
Definition buffer.h:251
Base class for all GbxUtilAcfr exceptions.
Definition gbxutilacfr/exceptions.h:66
Utility namespace (part of SICK-ACFR driver)
Definition buffer.h:21
BufferType
Buffer type defines behavior when the buffer is full
Definition buffer.h:25
@ BufferTypeCircular
Definition buffer.h:28
@ BufferTypeQueue
Definition buffer.h:31
 

Generated for GearBox by  doxygen 1.4.5