Slicer 4.2
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
itkTimeSeriesDatabaseHelper.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines