INTRODUCTION
Overview
Download and Install
Documentation
Publications

REPOSITORY
Libraries

DEVELOPER
Dev Guide
Dashboard

PEOPLE
Contributors
Users

SourceForge.net Logo
Project
Download
Mailing lists

 

         

store.h

00001 /*
00002  * GearBox Project: Peer-Reviewed Open-Source Libraries for Robotics
00003              http://gearbox.sf.net/
00004  * Copyright (c) 2004-2010 Alex Brooks, Alexei Makarenko, Tobias Kaupp
00005  *
00006  * This distribution is licensed to you under the terms described in
00007  * the LICENSE file included in this distribution.
00008  *
00009  */
00010 
00011 #ifndef GBXICEUTILACFR_STORE_H
00012 #define GBXICEUTILACFR_STORE_H
00013 
00014 #include <gbxutilacfr/exceptions.h>
00015 
00016 #include <IceUtil/Monitor.h>
00017 #include <IceUtil/Mutex.h>
00018 #include <IceUtil/Time.h>
00019 
00020 namespace gbxiceutilacfr {
00021 
00041 template<class Type>
00042 class Store : public IceUtil::Monitor<IceUtil::Mutex>
00043 {
00044 public:
00045 
00046     Store();
00047     virtual ~Store();
00048 
00052     bool isEmpty() const;
00053     
00055     bool isNewData() const;
00056 
00058     void set( const Type & obj );
00059 
00063     void get( Type & obj );
00064 
00068     void peek( Type & obj ) const;
00069 
00079     int  getNext( Type & obj, int timeoutMs=-1 );
00080     
00083     void purge();
00084 
00085 protected:
00086     
00087     // local copy of the object
00088     Type obj_;
00089 
00090     // Reimplement this function for non-standard types.
00091     virtual void internalGet( Type & obj ) const ;
00092     
00093     // Reimplement this function for non-standard types.
00094     virtual void internalSet( const Type & obj );
00095 
00096 private:
00097 
00098 
00099     bool isEmpty_;
00100     
00101     // flag to keep track of new data.
00102     bool isNewData_;
00103 
00104     // internal implementation of front( obj, -1 ); returns 0.
00105     int  getNextNoWait( Type & obj );
00106 
00107 };
00108 
00109 
00111 
00112 template<class Type>
00113 Store<Type>::Store()
00114     : isEmpty_(true),
00115       isNewData_(false)
00116 {
00117 }
00118 
00119 template<class Type>
00120 Store<Type>::~Store()
00121 {
00122 }
00123 
00124 template<class Type>
00125 bool Store<Type>::isEmpty() const
00126 {
00127     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00128     return isEmpty_;
00129 }
00130 
00131 template<class Type>
00132 bool Store<Type>::isNewData() const
00133 {
00134     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00135     return isNewData_;
00136 }
00137 
00138 template<class Type>
00139 void Store<Type>::get( Type & obj )
00140 {
00141     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00142     if ( !isEmpty_ )
00143     {
00144         internalGet( obj );
00145         isNewData_ = false;
00146     }
00147     else
00148     {
00149         throw gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty Store." );
00150     }
00151 }
00152 
00153 template<class Type>
00154 void Store<Type>::peek( Type & obj ) const
00155 {
00156     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00157     if ( !isEmpty_ )
00158     {
00159         internalGet( obj );
00160         // do NOT set isNewData_ to false
00161     }
00162     else
00163     {
00164         throw gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty Store." );
00165     }
00166 }
00167 
00168 template<class Type>
00169 int Store<Type>::getNext( Type & obj, int timeoutMs )
00170 {
00171     // special case: infinite wait time
00172     if ( timeoutMs == -1 ) {
00173         return getNextNoWait( obj );
00174     }
00175 
00176     // finite wait time
00177     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00178 
00179     // if already have data in the buffer, return it and get out
00180     if ( isNewData_ )
00181     {
00182         internalGet( obj );
00183         isNewData_ = false;
00184         return 0;
00185     }
00186 
00187     // empty buffer: figure out when to wake up
00188     // notice that we are still holding the lock, so it's ok to call timedWait()
00189     if (  this->timedWait( IceUtil::Time::milliSeconds( timeoutMs ) ) )  
00190     {
00191         // someone woke us up, we are holding the lock again
00192         // check new data again (could be a spurious wakeup)
00193         if ( isNewData_ ) 
00194         {
00195             internalGet( obj );
00196             isNewData_ = false;
00197             return 0;
00198         }
00199         else {
00200             // spurious wakup, don't wait again, just return
00201             return 1;
00202         }
00203     }
00204     else {
00205         // wait timedout, nobody woke us up
00206         return -1;
00207     }
00208 }
00209 
00210 template<class Type>
00211 int Store<Type>::getNextNoWait( Type & obj )
00212 {
00213     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00214 
00215     // check the condition before and after waiting to deal with spurious wakeups
00216     // (see Ice manual sec. 28.9.2)
00217     while ( !isNewData_ ) 
00218     {
00219         this->wait();
00220     }
00221    
00222     internalGet( obj );
00223     isNewData_ = false;
00224     return 0;
00225 }
00226 
00227 // NOTE: see notes on efficient notification in Ice sec. 28.9.3
00228 template<class Type>
00229 void Store<Type>::set( const Type &obj )
00230 {
00231     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00232     
00233     internalSet( obj );
00234 
00235     // mark as having new data (nobody has looked at it yet)
00236     isNewData_ = true;
00237     
00238     // mark Store non-empty (only usefull the very first time)
00239     isEmpty_ = false;
00240     
00241     // wakeup someone who's waiting for an update
00242     this->notify();
00243 }
00244 
00245 template<class Type>
00246 void Store<Type>::purge()
00247 {
00248     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00249     isEmpty_ = true;
00250 }
00251 
00252 template<class Type>
00253 void Store<Type>::internalGet( Type & obj ) const
00254 {
00255     obj = obj_;
00256 }
00257 
00258 template<class Type>    
00259 void Store<Type>::internalSet( const Type & obj )
00260 {
00261     obj_ = obj;
00262 }
00263 
00264 } // end namespace
00265 
00266 #endif
 

Generated for GearBox by  doxygen 1.4.5