Cache.h 5.3 KB

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