|
Slicer 4.2
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
|
00001 #ifndef __itkTimeSeriesDatabaseHelper_h 00002 #define __itkTimeSeriesDatabaseHelper_h 00003 #include <list> 00004 #include <iostream> 00005 #include <map> 00006 #include <string> 00007 #include <cstdarg> 00008 #include <cassert> 00009 00010 namespace itk { 00011 namespace TimeSeriesDatabaseHelper { 00013 /* 00014 * counted_ptr - simple reference counted pointer. 00015 * 00016 * The is a non-intrusive implementation that allocates an additional 00017 * int and pointer for every counted object. 00018 */ 00019 /* For ANSI-challenged compilers, you may want to #define 00020 * NO_MEMBER_TEMPLATES or explicit */ 00021 #define NO_MEMBER_TEMPLATES 00022 template <class X> class counted_ptr 00023 { 00024 public: 00025 typedef X element_type; 00026 00027 explicit counted_ptr(X* p = 0) 00028 : itsCounter(0) {if (p) itsCounter = new counter(p);} 00029 ~counted_ptr() 00030 {release();} 00031 counted_ptr(const counted_ptr& r) throw() 00032 {acquire(r.itsCounter);} 00033 counted_ptr& operator=(const counted_ptr& r) 00034 { 00035 if (this != &r) { 00036 release(); 00037 acquire(r.itsCounter); 00038 } 00039 return *this; 00040 } 00041 00042 #ifndef NO_MEMBER_TEMPLATES 00043 template <class Y> friend class counted_ptr<Y>; 00044 template <class Y> counted_ptr(const counted_ptr<Y>& r) throw() 00045 {acquire(r.itsCounter);} 00046 template <class Y> counted_ptr& operator=(const counted_ptr<Y>& r) 00047 { 00048 if (this != &r) { 00049 release(); 00050 acquire(r.itsCounter); 00051 } 00052 return *this; 00053 } 00054 #endif /// NO_MEMBER_TEMPLATES 00055 00056 X& operator*() const throw() {return *itsCounter->ptr;} 00057 X* operator->() const throw() {return itsCounter->ptr;} 00058 X* get() const throw() {return itsCounter ? itsCounter->ptr : 0;} 00059 bool unique() const throw() 00060 {return (itsCounter ? itsCounter->count == 1 : true);} 00061 00062 private: 00063 00064 struct counter { 00065 counter(X* p = 0, unsigned c = 1) : ptr(p), count(c) {} 00066 X* ptr; 00067 unsigned count; 00068 }* itsCounter; 00069 00070 void acquire(counter* c) throw() 00071 { 00072 itsCounter = c; 00073 if (c) ++c->count; 00074 } 00075 00076 void release() 00077 { 00078 if (itsCounter) { 00079 if (--itsCounter->count == 0) { 00080 delete itsCounter->ptr; 00081 delete itsCounter; 00082 } 00083 itsCounter = 0; 00084 } 00085 } 00086 }; 00087 00089 00090 using namespace std; 00091 00092 00093 #ifdef NDEBUG 00094 #define IF_DEBUG(x) 00095 #else 00096 #define IF_DEBUG(x) x 00097 #endif 00098 00099 00118 template <typename key_type, typename value_type> 00119 class LRUCache 00120 { 00121 public: 00126 LRUCache(unsigned maxsize_ = 100) 00127 : maxsize(maxsize_) 00128 { 00129 } 00130 00131 void set_maxsize ( unsigned maxsize_ ) { 00132 maxsize = maxsize_; 00133 } 00134 00135 unsigned get_maxsize () { 00136 return maxsize; 00137 } 00138 00139 ~LRUCache() 00140 { 00141 clear(); 00142 } 00143 00146 size_t size() 00147 { 00148 return lru_list.size(); 00149 } 00150 00153 bool empty() 00154 { 00155 return lru_list.empty(); 00156 } 00157 00160 void clear() 00161 { 00162 lru_list.clear(); 00163 table.clear(); 00164 IF_DEBUG(stats.clear()); 00165 } 00166 00169 void insert(const key_type& key, const value_type& value) 00170 { 00175 // 00176 value_type* valptr = find(key); 00177 00179 // 00180 if (valptr) 00181 { 00183 // 00184 *valptr = value; 00185 } 00186 else 00187 { 00191 lru_list.push_front(key); 00192 cached_value cv(value, lru_list.begin()); 00193 table.insert(make_pair(key, cv)); 00194 00197 // 00198 if (lru_list.size() > maxsize) 00199 { 00200 key_type lru_key = lru_list.back(); 00201 table.erase(lru_key); 00202 lru_list.pop_back(); 00203 00204 IF_DEBUG(stats.removed++); 00205 } 00206 } 00207 } 00208 00217 value_type* find(const key_type& key) 00218 { 00219 table_iter ti = table.find(key); 00220 00221 IF_DEBUG(stats.finds++); 00222 00223 if (ti == table.end()) 00224 return 0; 00225 00226 IF_DEBUG(stats.finds_hit++); 00227 00230 // 00231 list_iter li = ti->second.cache_i; 00232 lru_list.splice(lru_list.begin(), lru_list, li); 00233 00234 return &(ti->second.value); 00235 } 00236 00242 void debug_dump(ostream& ostr = cerr) 00243 { 00244 ostr << "Debug dump of LRUCache\n"; 00245 ostr << "-------------------\n\n"; 00246 00247 if (lru_list.empty()) 00248 { 00249 ostr << "The cache is empty\n"; 00250 } 00251 00252 ostr << "Sorted from MRU to LRU:\n\n"; 00253 00254 for (list_iter i = lru_list.begin(); i != lru_list.end(); ++i) 00255 { 00256 ostr << "Key: " << *i << endl; 00257 00258 table_iter ti = table.find(*i); 00259 assert(ti != table.end()); 00260 00261 ostr << "Value: " << ti->second.value << "\n|\n"; 00262 } 00263 00264 ostr << endl; 00265 } 00266 00271 #ifndef NDEBUG 00272 void statistics(ostream& ostr = cerr) const 00273 { 00274 ostr << "LRUCache statistics\n"; 00275 ostr << "----------------\n\n"; 00276 ostr << format_str("Max size: %ld, cur size %ld. Cache is %5.2lf%% full\n\n", 00277 maxsize, lru_list.size(), 100.0 * lru_list.size() / maxsize); 00278 ostr << format_str("Lookups: %7ld\nHits: %7ld\nHit rate: %7.2lf%%\n\n", 00279 stats.finds, stats.finds_hit, 100.0 * stats.finds_hit / (stats.finds+1e-15)); 00280 ostr << format_str("Items removed by LRU: %ld\n\n", stats.removed); 00281 } 00282 #else 00283 void statistics(ostream & vtkNotUsed(ostr) ) const 00284 { 00285 } 00286 #endif /// NDEBUG 00287 00288 #ifndef NDEBUG 00289 00290 00291 00292 string format_str(const char* format, ...) const 00293 { 00294 va_list arglist; 00295 va_start(arglist, format); 00296 char* buf = new char[10000]; 00297 00298 vsprintf(buf, format, arglist); 00299 string ret = buf; 00300 delete [] buf; 00301 return ret; 00302 } 00303 #endif /// NDEBUG 00304 00305 private: 00306 typedef typename list<key_type>::iterator list_iter; 00307 00308 struct cached_value 00309 { 00310 cached_value(value_type value_, list_iter cache_i_) 00311 : value(value_), cache_i(cache_i_) 00312 { 00313 } 00314 00315 value_type value; 00316 list_iter cache_i; 00317 }; 00318 00319 typedef typename map<key_type, cached_value>::iterator table_iter; 00320 00323 unsigned maxsize; 00324 00331 list<key_type> lru_list; 00332 00335 map<key_type, cached_value> table; 00336 00337 #ifndef NDEBUG 00338 00339 struct cache_statistics 00340 { 00341 cache_statistics() 00342 { 00343 clear(); 00344 } 00345 00346 void clear() 00347 { 00348 finds = finds_hit = removed = 0; 00349 } 00350 00351 typedef unsigned long ulong; 00352 00353 ulong finds; 00354 ulong finds_hit; 00355 ulong removed; 00356 } stats; 00357 #endif 00358 }; 00359 } 00360 } 00361 #endif
1.7.4