13 #ifndef UT_LRU_CACHE_H
14 #define UT_LRU_CACHE_H
26 #include <type_traits>
27 #include <unordered_map>
50 "Pointer types need their own size function.");
69 exint(*SizeFunc)(
const V &) = UTlruGetItemSize<V>,
70 bool(*InUseFunc)(
const V &) = UTlruGetItemInUse<V>,
75 using ValueType = std::pair<const K, V>;
76 using ValueList = std::list<ValueType> ;
77 using KeyIteratorMap = std::unordered_map<K, typename ValueList::iterator>;
79 template<
typename PROXIED,
typename TYPE>
82 ValueList myValueList;
83 KeyIteratorMap myKeyMap;
93 template<
typename PROXIED,
typename TYPE>
96 using proxied_iterator = PROXIED;
109 other.myLock->readLock();
111 myLock = other.myLock;
116 myIt = std::move(other.myIt);
117 other.myIt = proxied_iterator();
118 myLock = other.myLock;
119 other.myLock =
nullptr;
124 other.myLock->readLock();
126 myLock = other.myLock;
132 myIt = std::move(other.myIt);
133 other.myIt = proxied_iterator();
134 myLock = other.myLock;
135 other.myLock =
nullptr;
143 myLock->readUnlock();
154 return myIt == other.myIt;
158 return myIt != other.myIt;
165 myIt(it), myLock(lock) { }
168 proxied_iterator myIt;
174 using iterator = iterator_base<typename ValueList::iterator, std::pair<const K, V>>;
177 using const_iterator = iterator_base<typename ValueList::const_iterator, const std::pair<const K, V>>;
187 mySizeFunc(SizeFunc),
188 myInUseFunc(InUseFunc),
192 myLock = UTmakeUnique<L>();
200 if (max_size >= myMaxSize)
202 myMaxSize = max_size;
206 myMaxSize = max_size;
213 myLock->writeUnlock();
230 myLock->readUnlock();
243 myLock->readUnlock();
254 bool found = (myKeyMap.find(key) != myKeyMap.end());
257 myLock->readUnlock();
272 auto itK = myKeyMap.find(key);
273 if (itK == myKeyMap.end())
276 myLock->readUnlock();
277 return iterator(myValueList.end(),
nullptr);
281 if (itK->second != myValueList.begin())
283 myValueList.splice(myValueList.begin(), myValueList,
285 itK->second = myValueList.begin();
288 return iterator(itK->second, myLock.get());
297 std::pair<iterator, bool>
309 std::pair<iterator, bool>
result;
310 auto itK = myKeyMap.find(key);
311 if (itK != myKeyMap.end() && !evict)
319 result = std::make_pair(
iterator(itK->second,myLock.get()),
false);
323 if (itK != myKeyMap.end())
327 myCurrentSize -= mySizeFunc((itK->second)->second);
328 myCurrentSize += mySizeFunc(
value);
335 myValueList.splice(myValueList.begin(), myValueList,
338 myValueList.begin()->second = std::move(
value);
339 itK->second = myValueList.begin();
341 result = std::make_pair(
342 iterator(itK->second, myLock.get()),
true);
346 myCurrentSize += mySizeFunc(
value);
350 myValueList.push_front(std::make_pair(key, std::move(
value)));
351 myKeyMap.insert(std::make_pair(key, myValueList.begin()));
353 result = std::make_pair(
354 iterator(myValueList.begin(), myLock.get()),
true);
359 myLock->writeUnlock();
369 bool updated =
false;
373 auto itK = myKeyMap.find(key);
374 if (itK != myKeyMap.end())
376 myCurrentSize -= mySizeFunc((itK->second)->second);
377 myValueList.erase(itK->second);
383 myLock->writeUnlock();
393 bool updated =
false;
397 auto itK = myKeyMap.find(key);
398 if (itK != myKeyMap.end())
400 myCurrentSize -= mySizeFunc((itK->second)->second);
403 value = std::move((itK->second)->second);
405 myValueList.erase(itK->second);
411 myLock->writeUnlock();
419 if (myLock) myLock->writeLock();
425 if (myLock) myLock->writeUnlock();
431 if (myLock) myLock->readLock();
432 return iterator(myValueList.begin(), myLock.get());
439 return iterator(myValueList.end(),
nullptr);
445 if (myLock) myLock->readLock();
460 void prune(
typename ValueList::iterator *itSkipV =
nullptr)
462 for (
auto ritV = myValueList.rbegin();
463 myCurrentSize > myMaxSize && ritV != myValueList.rend(); ++ritV)
465 if ((itSkipV && ritV.base() == *itSkipV) ||
466 myInUseFunc(ritV->second))
471 myCurrentSize -= mySizeFunc(ritV->second);
473 auto itK = myKeyMap.find(ritV->first);
477 auto itV = myValueList.erase(std::prev(ritV.base()));
478 ritV =
typename ValueList::reverse_iterator(itV);
iterator_base(proxied_iterator it, L *lock)
std::pair< iterator, bool > insert(const K &key, V &&value, bool evict=false)
bool steal(const K &key, V &&value)
GLsizei const GLfloat * value
iterator find(const K &key)
bool UTlruGetItemInUse(const V &)
**But if you need a result
bool operator!=(const iterator_base &other) const
iterator_base< typename ValueList::iterator, std::pair< const cl_mem, ut_clBuffer >> iterator
A iterator pointing to mutable values.
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
iterator_base< typename ValueList::const_iterator, const std::pair< const cl_mem, ut_clBuffer >> const_iterator
A const iterator pointing to immutable values.
exint currentSize() const
iterator begin()
Returns an iterator to the front-most item in the LRU cache.
iterator_base & operator=(iterator_base &&other)
exint UTlruGetItemSize(const V &)
iterator_base(iterator_base &&other)
bool operator==(const iterator_base &other) const
iterator end()
Returns an iterator to the end of the LRU list.
pointer operator->() const
std::function< T > UT_Function
exint maxSize() const
Returns the current maximum size of the cache.
UT_LRUCache(exint max_size=SYS_EXINT_MAX)
void setMaxSize(exint max_size)
bool contains(const K &key) const
const_iterator begin() const
Returns a const iterator to the front-most item in the LRU cache.
const_iterator end() const
Returns a const iterator to the end of the LRU list.
exint count() const
Returns the number of items in the cache.
iterator_base(const iterator_base &other)
iterator_base & operator=(const iterator_base &other)
std::bidirectional_iterator_tag iterator_category
reference operator*() const
friend class iterator_base
iterator_base & operator++()
void clear()
Clears the cache completely.
iterator_base & operator--()
std::ptrdiff_t difference_type