Slicer  4.11
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.
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(nullptr) {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 : nullptr;}
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 = nullptr;
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 nullptr;
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