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-2008 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 <gbxsickacfr/gbxutilacfr/exceptions.h>
00015 
00016 #include <IceUtil/Monitor.h>
00017 #include <IceUtil/Mutex.h>
00018 #include <IceUtil/Time.h>
00019 
00020 namespace gbxsickacfr {
00021 namespace gbxiceutilacfr {
00022 
00039 template<class Type>
00040 class Store : public IceUtil::Monitor<IceUtil::Mutex>
00041 {
00042 public:
00043 
00044     Store();
00045     virtual ~Store();
00046 
00050     bool isEmpty() const;
00051     
00053     bool isNewData() const;
00054 
00056     void set( const Type & obj );
00057 
00061     void get( Type & obj ) const;
00062 
00073     int  getNext( Type & obj, int timeoutMs=-1 ) const;
00074     
00077     void purge();
00078 
00079 protected:
00080     
00081     // local copy of the object
00082     Type obj_;
00083 
00084     // Reimplement this function for non-standard types.
00085     virtual void internalGet( Type & obj ) const ;
00086     
00087     // Reimplement this function for non-standard types.
00088     virtual void internalSet( const Type & obj );
00089 
00090 private:
00091 
00092 
00093     bool isEmpty_;
00094     
00095     // flag to keep track of new data. Make it mutable so that get() functions can be const.
00096     mutable bool isNewData_;
00097 
00098     // internal implementation of front( obj, -1 ); returns 0.
00099     int  getNextNoWait( Type & obj ) const;
00100 
00101 };
00102 
00103 
00105 
00106 template<class Type>
00107 Store<Type>::Store()
00108     : isEmpty_(true),
00109       isNewData_(false)
00110 {
00111 }
00112 
00113 template<class Type>
00114 Store<Type>::~Store()
00115 {
00116 }
00117 
00118 template<class Type>
00119 bool Store<Type>::isEmpty() const
00120 {
00121     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00122     return isEmpty_;
00123 }
00124 
00125 template<class Type>
00126 bool Store<Type>::isNewData() const
00127 {
00128     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00129     return isNewData_;
00130 }
00131 
00132 template<class Type>
00133 void Store<Type>::get( Type & obj ) const
00134 {
00135     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00136     if ( !isEmpty_ )
00137     {
00138         internalGet( obj );
00139         isNewData_ = false;
00140     }
00141     else
00142     {
00143         throw gbxsickacfr::gbxutilacfr::Exception( ERROR_INFO, "trying to read from an empty Store." );
00144     }
00145 }
00146 
00147 template<class Type>
00148 int Store<Type>::getNext( Type & obj, int timeoutMs ) const
00149 {
00150     // special case: infinite wait time
00151     if ( timeoutMs == -1 ) {
00152         return getNextNoWait( obj );
00153     }
00154 
00155     // finite wait time
00156     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00157 
00158     // if already have data in the buffer, return it and get out
00159     if ( isNewData_ )
00160     {
00161         internalGet( obj );
00162         isNewData_ = false;
00163         return 0;
00164     }
00165 
00166     // empty buffer: figure out when to wake up
00167     // notice that we are still holding the lock, so it's ok to call timedWait()
00168     if (  this->timedWait( IceUtil::Time::milliSeconds( timeoutMs ) ) )  
00169     {
00170         // someone woke us up, we are holding the lock again
00171         // check new data again (could be a spurious wakeup)
00172         if ( isNewData_ ) 
00173         {
00174             internalGet( obj );
00175             isNewData_ = false;
00176             return 0;
00177         }
00178         else {
00179             // spurious wakup, don't wait again, just return
00180             return 1;
00181         }
00182     }
00183     else {
00184         // wait timedout, nobody woke us up
00185         return -1;
00186     }
00187 }
00188 
00189 template<class Type>
00190 int Store<Type>::getNextNoWait( Type & obj ) const
00191 {
00192     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00193 
00194     // check the condition before and after waiting to deal with spurious wakeups
00195     // (see Ice manual sec. 28.9.2)
00196     while ( !isNewData_ ) 
00197     {
00198         this->wait();
00199     }
00200    
00201     internalGet( obj );
00202     isNewData_ = false;
00203     return 0;
00204 }
00205 
00206 // NOTE: see notes on efficient notification in Ice sec. 28.9.3
00207 template<class Type>
00208 void Store<Type>::set( const Type &obj )
00209 {
00210     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00211     
00212     internalSet( obj );
00213 
00214     // mark as having new data (nobody has looked at it yet)
00215     isNewData_ = true;
00216     
00217     // mark Store non-empty (only usefull the very first time)
00218     isEmpty_ = false;
00219     
00220     // wakeup someone who's waiting for an update
00221     this->notify();
00222 }
00223 
00224 template<class Type>
00225 void Store<Type>::purge()
00226 {
00227     IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this);
00228     isEmpty_ = true;
00229 }
00230 
00231 template<class Type>
00232 void Store<Type>::internalGet( Type & obj ) const
00233 {
00234     obj = obj_;
00235 }
00236 
00237 template<class Type>    
00238 void Store<Type>::internalSet( const Type & obj )
00239 {
00240     obj_ = obj;
00241 }
00242 
00243 }
00244 } // end namespace
00245 
00246 #endif
 

Generated for GearBox by  doxygen 1.4.5