Cache.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #pragma once
  2. #include "HashMap.h"
  3. #include "Zeit.h"
  4. namespace Framework
  5. {
  6. enum class CacheCleanupStrategy
  7. {
  8. LONGEST_NOT_USED,
  9. OLDEST,
  10. RANDOM
  11. };
  12. template<typename T> struct CacheEntry
  13. {
  14. __int64 created;
  15. __int64 lastUsed;
  16. T value;
  17. };
  18. template<typename K, typename T> class CacheIterator
  19. {
  20. private:
  21. MapIterator<K, CacheEntry<T>> delegate;
  22. public:
  23. CacheIterator(MapIterator<K, CacheEntry<T>> delegate)
  24. : delegate(delegate)
  25. {}
  26. CacheIterator(const CacheIterator<K, T>& it)
  27. {
  28. delegate = it.delegate;
  29. }
  30. CacheIterator<K, T>& operator=(CacheIterator<K, T> r)
  31. {
  32. delegate = r.delegate;
  33. return *this;
  34. }
  35. bool hasNext()
  36. {
  37. return delegate.hasNext();
  38. }
  39. MapEntry<K, T> operator*()
  40. {
  41. return MapEntry<K, T>(delegate.operator->().getKey(),
  42. delegate.operator->().getValue().value);
  43. }
  44. CacheIterator<K, T> next()
  45. {
  46. return CacheIterator(delegate.next());
  47. }
  48. operator bool()
  49. {
  50. return delegate;
  51. }
  52. operator MapEntry<K, T>()
  53. {
  54. return MapEntry<K, T>(
  55. delegate->getKey(), delegate->getValue().value);
  56. }
  57. CacheIterator<K, T>& operator++() //! prefix
  58. {
  59. ++delegate;
  60. return *this;
  61. }
  62. CacheIterator<K, T> operator++(int) //! postfix
  63. {
  64. CacheIterator<K, T> temp(*this);
  65. ++delegate;
  66. return temp;
  67. }
  68. MapEntry<K, T> operator->()
  69. {
  70. return MapEntry<K, T>(
  71. delegate->getKey(), delegate->getValue().value);
  72. }
  73. void set(MapEntry<K, T> val)
  74. {
  75. time_t zeit = time(0);
  76. delegate.set(MapEntry<K, CacheEntry<T>>(
  77. val.getKey(), CacheEntry<T>{zeit, zeit, val.getValue()}));
  78. }
  79. bool operator!=(CacheIterator<K, T>& r)
  80. {
  81. return delegate != r.delegate;
  82. }
  83. };
  84. template<typename K, typename T> class Cache
  85. : public virtual ReferenceCounter
  86. {
  87. private:
  88. HashMap<K, CacheEntry<T>>* cache;
  89. CacheCleanupStrategy cleanup;
  90. int maxSize;
  91. void removeOneElement()
  92. {
  93. switch (cleanup)
  94. {
  95. case CacheCleanupStrategy::LONGEST_NOT_USED:
  96. {
  97. K key;
  98. __int64 t = -1;
  99. for (MapEntry<K, CacheEntry<T>> e : *cache)
  100. {
  101. if (t < 0 || t > e.getValue().lastUsed)
  102. {
  103. t = e.getValue().lastUsed;
  104. key = e.getKey();
  105. }
  106. }
  107. if (t >= 0) cache->remove(key);
  108. break;
  109. }
  110. case CacheCleanupStrategy::OLDEST:
  111. {
  112. K key;
  113. __int64 t = -1;
  114. for (MapEntry<K, CacheEntry<T>> e : *cache)
  115. {
  116. if (t < 0 || t > e.getValue().created)
  117. {
  118. t = e.getValue().created;
  119. key = e.getKey();
  120. }
  121. }
  122. if (t >= 0) cache->remove(key);
  123. break;
  124. }
  125. case CacheCleanupStrategy::RANDOM:
  126. {
  127. int size = cache->getSize();
  128. int index = (int)(((double)rand() / RAND_MAX) * size);
  129. auto it = cache->begin();
  130. for (int i = 0; i < index; i++)
  131. ++it;
  132. cache->remove(it.operator->().getKey());
  133. break;
  134. }
  135. }
  136. }
  137. public:
  138. Cache(
  139. int size, std::function<int(K)> hash, CacheCleanupStrategy cleanup)
  140. : ReferenceCounter(),
  141. cleanup(cleanup),
  142. maxSize(size)
  143. {
  144. cache = new HashMap<K, CacheEntry<T>>(size, hash);
  145. }
  146. ~Cache()
  147. {
  148. cache->release();
  149. }
  150. void put(K key, T value)
  151. {
  152. time_t zeit = time(0);
  153. if (cache->getSize() >= maxSize && !cache->has(key))
  154. removeOneElement();
  155. cache->put(key, {zeit, zeit, value});
  156. }
  157. void remove(K key)
  158. {
  159. cache->remove(key);
  160. }
  161. T get(K key) const
  162. {
  163. CacheEntry<T> entry = cache->get(key);
  164. entry.lastUsed = time(0);
  165. cache->put(key, entry);
  166. return entry.value;
  167. }
  168. bool has(K key) const
  169. {
  170. return cache->has(key);
  171. }
  172. int getCurrentSize() const
  173. {
  174. return cache->getSize();
  175. }
  176. int getMaxSize() const
  177. {
  178. return maxSize;
  179. }
  180. void reset() const
  181. {
  182. cache->leeren();
  183. }
  184. CacheIterator<K, T> begin()
  185. {
  186. return CacheIterator<K, T>(cache->begin());
  187. }
  188. CacheIterator<K, T> end()
  189. {
  190. return CacheIterator<K, T>(cache->end());
  191. }
  192. };
  193. } // namespace Framework