Slicer  4.8
Slicer is a multi-platform, free and open source software package for visualization and medical image computing
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
itkTimeSeriesDatabaseHelper.h
Go to the documentation of this file.
1 #ifndef itkTimeSeriesDatabaseHelper_h
2 #define itkTimeSeriesDatabaseHelper_h
3 #include <list>
4 #include <iostream>
5 #include <map>
6 #include <string>
7 #include <cstdarg>
8 #include <cassert>
9 
10 namespace itk {
11  namespace TimeSeriesDatabaseHelper {
13  /*
14  * counted_ptr - simple reference counted pointer.
15  *
16  * The is a non-intrusive implementation that allocates an additional
17  * int and pointer for every counted object.
18  */
19 
20  template <class ElementType> class counted_ptr
21  {
22  public:
23 
24  explicit counted_ptr(ElementType* p = 0)
25  : m_ItsCounter(0) {if (p) m_ItsCounter = new counter(p);}
27  {release();}
28  counted_ptr(const counted_ptr& r) throw()
29  {acquire(r.m_ItsCounter);}
31  {
32  if (this != &r) {
33  release();
34  acquire(r.m_ItsCounter);
35  }
36  return *this;
37  }
38 
39  ElementType& operator*() const throw() {return *m_ItsCounter->ptr;}
40  ElementType* operator->() const throw() {return m_ItsCounter->ptr;}
41  ElementType* get() const throw() {return m_ItsCounter ? m_ItsCounter->ptr : 0;}
42  bool unique() const throw()
43  {return (m_ItsCounter ? m_ItsCounter->count == 1 : true);}
44 
45  private:
46 
47  struct counter {
48  counter(ElementType* p = 0, unsigned c = 1) : ptr(p), count(c) {}
49  ElementType* ptr;
50  unsigned count;
51  }* m_ItsCounter;
52 
53  void acquire(counter* c) throw()
54  {
55  m_ItsCounter = c;
56  if (c) ++c->count;
57  }
58 
59  void release()
60  {
61  if (m_ItsCounter) {
62  if (--m_ItsCounter->count == 0) {
63  delete m_ItsCounter->ptr;
64  delete m_ItsCounter;
65  }
66  m_ItsCounter = 0;
67  }
68  }
69  };
70 
72 
73  using namespace std;
74 
75 
76 #ifdef NDEBUG
77 #define IF_DEBUG(x)
78 #else
79 #define IF_DEBUG(x) x
80 #endif
81 
82 
101  template <typename KeyType, typename ValueType>
102  class LRUCache
103  {
104  public:
109  LRUCache(unsigned maxsize_ = 100)
110  : maxsize(maxsize_)
111  {
112  }
113 
114  void set_maxsize ( unsigned maxsize_ ) {
115  maxsize = maxsize_;
116  }
117 
118  unsigned get_maxsize () {
119  return maxsize;
120  }
121 
123  {
124  clear();
125  }
126 
129  size_t size()
130  {
131  return lru_list.size();
132  }
133 
136  bool empty()
137  {
138  return lru_list.empty();
139  }
140 
143  void clear()
144  {
145  lru_list.clear();
146  table.clear();
147  IF_DEBUG(stats.clear());
148  }
149 
152  void insert(const KeyType& key, const ValueType& value)
153  {
158  //
159  ValueType* valptr = find(key);
160 
162  //
163  if (valptr)
164  {
166  //
167  *valptr = value;
168  }
169  else
170  {
174  lru_list.push_front(key);
175  cached_value cv(value, lru_list.begin());
176  table.insert(make_pair(key, cv));
177 
180  //
181  if (lru_list.size() > maxsize)
182  {
183  KeyType lru_key = lru_list.back();
184  table.erase(lru_key);
185  lru_list.pop_back();
186 
187  IF_DEBUG(stats.removed++);
188  }
189  }
190  }
191 
200  ValueType* find(const KeyType& key)
201  {
202  TableIteratorType ti = table.find(key);
203 
204  IF_DEBUG(stats.finds++);
205 
206  if (ti == table.end())
207  return 0;
208 
209  IF_DEBUG(stats.finds_hit++);
210 
213  //
214  ListIteratorType li = ti->second.cache_i;
215  lru_list.splice(lru_list.begin(), lru_list, li);
216 
217  return &(ti->second.value);
218  }
219 
225  void debug_dump(ostream& ostr = cerr)
226  {
227  ostr << "Debug dump of LRUCache\n";
228  ostr << "-------------------\n\n";
229 
230  if (lru_list.empty())
231  {
232  ostr << "The cache is empty\n";
233  }
234 
235  ostr << "Sorted from MRU to LRU:\n\n";
236 
237  for (ListIteratorType i = lru_list.begin(); i != lru_list.end(); ++i)
238  {
239  ostr << "Key: " << *i << endl;
240 
241  TableIteratorType ti = table.find(*i);
242  assert(ti != table.end());
243 
244  ostr << "Value: " << ti->second.value << "\n|\n";
245  }
246 
247  ostr << endl;
248  }
249 
254 #ifndef NDEBUG
255  void statistics(ostream& ostr = cerr) const
256  {
257  ostr << "LRUCache statistics\n";
258  ostr << "----------------\n\n";
259  ostr << format_str("Max size: %ld, cur size %ld. Cache is %5.2lf%% full\n\n",
260  maxsize, lru_list.size(), 100.0 * lru_list.size() / maxsize);
261  ostr << format_str("Lookups: %7ld\nHits: %7ld\nHit rate: %7.2lf%%\n\n",
262  stats.finds, stats.finds_hit, 100.0 * stats.finds_hit / (stats.finds+1e-15));
263  ostr << format_str("Items removed by LRU: %ld\n\n", stats.removed);
264  }
265 #else
266  void statistics(ostream & vtkNotUsed(ostr) ) const
267  {
268  }
269 #endif
270 
271  #ifndef NDEBUG
272  string format_str(const char* format, ...) const
276  {
277  va_list arglist;
278  va_start(arglist, format);
279  char* buf = new char[10000];
280 
281  vsprintf(buf, format, arglist);
282  string ret = buf;
283  delete [] buf;
284  return ret;
285  }
286 #endif
287 
288  private:
289  typedef typename list<KeyType>::iterator ListIteratorType;
290 
291  struct cached_value
292  {
293  cached_value(ValueType value_, ListIteratorType cache_i_)
294  : value(value_), cache_i(cache_i_)
295  {
296  }
297 
298  ValueType value;
299  ListIteratorType cache_i;
300  };
301 
302  typedef typename map<KeyType, cached_value>::iterator TableIteratorType;
303 
306  unsigned maxsize;
307 
314  list<KeyType> lru_list;
315 
318  map<KeyType, cached_value> table;
319 
320 #ifndef NDEBUG
321 
322  struct cache_statistics
323  {
324  cache_statistics()
325  {
326  clear();
327  }
328 
329  void clear()
330  {
331  finds = finds_hit = removed = 0;
332  }
333 
334  unsigned long finds;
335  unsigned long finds_hit;
336  unsigned long removed;
337  } stats;
338 #endif
339  };
340  }
341 }
342 #endif
LRU Cache.
Simplified inverse ITK transforms.
#define IF_DEBUG(x)
void insert(const KeyType &key, const ValueType &value)
counted_ptr & operator=(const counted_ptr &r)
counted_ptr(ElementType *p=0)
allocate a new counter