#pragma once #include "HashMap.h" #include "Zeit.h" namespace Framework { enum class CacheCleanupStrategy { LONGEST_NOT_USED, OLDEST, RANDOM }; template struct CacheEntry { __int64 created; __int64 lastUsed; T value; }; template class CacheIterator { private: MapIterator> delegate; public: CacheIterator(MapIterator> delegate) : delegate(delegate) {} CacheIterator(const CacheIterator& it) { delegate = it.delegate; } CacheIterator& operator=(CacheIterator r) { delegate = r.delegate; return *this; } bool hasNext() { return delegate.hasNext(); } MapEntry operator*() { return MapEntry(delegate.operator->().getKey(), delegate.operator->().getValue().value); } CacheIterator next() { return CacheIterator(delegate.next()); } operator bool() { return delegate; } operator MapEntry() { return MapEntry( delegate->getKey(), delegate->getValue().value); } CacheIterator& operator++() //! prefix { ++delegate; return *this; } CacheIterator operator++(int) //! postfix { CacheIterator temp(*this); ++delegate; return temp; } MapEntry operator->() { return MapEntry( delegate->getKey(), delegate->getValue().value); } void set(MapEntry val) { time_t zeit = time(0); delegate.set(MapEntry>( val.getKey(), CacheEntry{zeit, zeit, val.getValue()})); } bool operator!=(CacheIterator& r) { return delegate != r.delegate; } }; template class Cache : public virtual ReferenceCounter { private: HashMap>* cache; CacheCleanupStrategy cleanup; int maxSize; void removeOneElement() { switch (cleanup) { case CacheCleanupStrategy::LONGEST_NOT_USED: { K key; __int64 t = -1; for (MapEntry> e : *cache) { if (t < 0 || t > e.getValue().lastUsed) { t = e.getValue().lastUsed; key = e.getKey(); } } if (t >= 0) cache->remove(key); break; } case CacheCleanupStrategy::OLDEST: { K key; __int64 t = -1; for (MapEntry> e : *cache) { if (t < 0 || t > e.getValue().created) { t = e.getValue().created; key = e.getKey(); } } if (t >= 0) cache->remove(key); break; } case CacheCleanupStrategy::RANDOM: { int size = cache->getSize(); int index = (int)(((double)rand() / RAND_MAX) * size); auto it = cache->begin(); for (int i = 0; i < index; i++) ++it; cache->remove(it.operator->().getKey()); break; } } } public: Cache( int size, std::function hash, CacheCleanupStrategy cleanup) : ReferenceCounter(), cleanup(cleanup), maxSize(size) { cache = new HashMap>(size, hash); } ~Cache() { cache->release(); } void put(K key, T value) { time_t zeit = time(0); if (cache->getSize() >= maxSize && !cache->has(key)) removeOneElement(); cache->put(key, {zeit, zeit, value}); } void remove(K key) { cache->remove(key); } T get(K key) const { CacheEntry entry = cache->get(key); entry.lastUsed = time(0); cache->put(key, entry); return entry.value; } bool has(K key) const { return cache->has(key); } int getCurrentSize() const { return cache->getSize(); } int getMaxSize() const { return maxSize; } void reset() const { cache->leeren(); } CacheIterator begin() { return CacheIterator(cache->begin()); } CacheIterator end() { return CacheIterator(cache->end()); } }; } // namespace Framework