storage.hh
Go to the documentation of this file.
00001 
00037 #ifndef LibMultiSense_details_storage_hh
00038 #define LibMultiSense_details_storage_hh
00039 
00040 #include "details/utility/Thread.hh"
00041 
00042 #include <map>
00043 #include <set>
00044 
00045 namespace crl {
00046 namespace multisense {
00047 namespace details {
00048     
00049     //
00050     // A message storage interface
00051     //
00052     // Assumes a 1:1 relationship between template class and ID
00053 
00054     class MessageMap {
00055     public:
00056 
00057         template<class T> void store(const T& msg) {
00058             utility::ScopedLock lock(m_lock);
00059 
00060             Map::iterator it = m_map.find(MSG_ID(T::ID));
00061             if (m_map.end() != it) {
00062                 it->second.destroy<T>();
00063                 m_map.erase(it);
00064             }
00065 
00066             m_map[MSG_ID(T::ID)] = Holder::Create<T>(msg);
00067         };
00068 
00069         template<class T> Status extract(T& msg) {
00070             utility::ScopedLock lock(m_lock);
00071 
00072             Map::iterator it = m_map.find(MSG_ID(T::ID));
00073             if (m_map.end() == it)
00074                 return Status_Error;
00075 
00076             it->second.extract(msg);
00077             m_map.erase(it);
00078 
00079             return Status_Ok;
00080         };
00081         
00082     private:
00083 
00084         class Holder {
00085         public:
00086        
00087             Holder(void *r=NULL) : m_refP(r) {};
00088             
00089             template<class T> static Holder Create(const T& msg) {
00090                 return Holder(reinterpret_cast<void *>(new T(msg)));
00091             };
00092       
00093             template<class T> void destroy() {
00094                 if (NULL == m_refP)
00095                     CRL_EXCEPTION("destroying NULL reference");
00096                 delete reinterpret_cast<T*>(m_refP);
00097             };
00098         
00099             template<class T> void extract(T& msg) {
00100                 if (NULL == m_refP)
00101                     CRL_EXCEPTION("extracting NULL reference");
00102                 msg = *(reinterpret_cast<T*>(m_refP));
00103                 destroy<T>();
00104             };
00105             
00106         private:
00107             void *m_refP;
00108         };
00109 
00110         typedef std::map<wire::IdType, Holder> Map;
00111 
00112         utility::Mutex m_lock;
00113         Map            m_map;
00114     };
00115 
00116     //
00117     // A constant-depth cache.
00118     //
00119     // Up to [depth] entries will be cached.  Oldest entries
00120     // will be dropped on insertion once full.
00121     //
00122     // The age of an entry is determined by std::map<KEY,DATA>.lower_bound([min]).
00123     //
00124     // DATA objects are assumed to be allocated on the heap, and memory management
00125     // of the object is delegated here upon insert().
00126     //
00127     // For *_nolock() variations, lock-management must be 
00128     // done by the user.
00129 
00130     template<class KEY, class DATA>
00131     class DepthCache {
00132     public:
00133         
00134         DepthCache(std::size_t depth, KEY min) : 
00135             m_depth(depth),
00136             m_minimum(min) {};
00137 
00138         ~DepthCache() {
00139             utility::ScopedLock lock(m_lock);
00140 
00141             typename MapType::iterator it = m_map.begin();
00142             for(; it != m_map.end();) {
00143                 delete it->second;
00144                 m_map.erase(it++);
00145             }
00146         };
00147 
00148         utility::Mutex& mutex() { 
00149             return m_lock; 
00150         };
00151 
00152         DATA* find_nolock(KEY key) {
00153             return find_(key);
00154         };
00155 
00156         DATA* find(KEY key) {
00157             utility::ScopedLock lock(m_lock);
00158             return find_(key);
00159         };
00160 
00161         void insert_nolock(KEY key, DATA* data) {
00162             insert_(key, data);
00163         };
00164 
00165         void insert(KEY key, DATA* data) {
00166             utility::ScopedLock lock(m_lock);
00167             insert_(key, data);
00168         };
00169 
00170         void remove_nolock(KEY key) {
00171             remove_(key);
00172         };
00173 
00174         void remove(KEY key) {
00175             utility::ScopedLock lock(m_lock);
00176             remove_(key);
00177         };
00178 
00179     private:
00180 
00181         typedef std::map<KEY,DATA*> MapType;
00182 
00183         DATA* find_(KEY key) {
00184             typename MapType::iterator it = m_map.find(key);
00185 
00186             if (m_map.end() == it)
00187                 return NULL;
00188             else
00189                 return it->second;
00190         };
00191 
00192         void insert_(KEY key, DATA* data) {
00193             if (m_map.size() == m_depth)
00194                 pop_oldest_();
00195 
00196             m_map[key] = data;
00197         };
00198 
00199         void remove_(KEY key) {
00200             typename MapType::iterator it2 = m_map.find(key);
00201             if (m_map.end() != it2) {
00202                 delete it2->second;
00203                 m_map.erase(it2);
00204             }
00205         };
00206 
00207         void pop_oldest_() {
00208             typename MapType::iterator it2 = m_map.lower_bound(m_minimum);
00209             if (m_map.end() != it2) {
00210                 delete it2->second;
00211                 m_map.erase(it2);
00212             }
00213         };
00214 
00215         const std::size_t m_depth;
00216         const KEY         m_minimum; // for lower_bound()
00217 
00218         MapType           m_map;
00219         utility::Mutex    m_lock;
00220     };
00221 
00222 }}}; // namespaces
00223 
00224 #endif // LibMultiSense_details_storage_hh


multisense_lib
Author(s):
autogenerated on Thu Aug 27 2015 14:01:11