Periodically prune empty elements in weak cache

pull/541/head
Kyle Cooley 6 years ago committed by Andrei Kortunov
parent 0096951f25
commit 7eb1b14b21

@ -3,6 +3,7 @@
#include <memory> #include <memory>
#include <unordered_map> #include <unordered_map>
#include <vector>
namespace cache namespace cache
{ {
@ -19,18 +20,19 @@ namespace cache
class iterator class iterator
{ {
public: public:
iterator(typename Map::iterator current, typename Map::iterator end); iterator(WeakCache* cache, typename Map::iterator current, typename Map::iterator end);
iterator& operator++(); iterator& operator++();
bool operator==(const iterator& other); bool operator==(const iterator& other);
bool operator!=(const iterator& other); bool operator!=(const iterator& other);
StrongPtr operator*(); StrongPtr operator*();
private: private:
WeakCache* mCache;
typename Map::iterator mCurrent, mEnd; typename Map::iterator mCurrent, mEnd;
StrongPtr mPtr; StrongPtr mPtr;
}; };
/// Stores a weak pointer to the item. /// Stores a weak pointer to the item.
void insert(Key key, StrongPtr value); void insert(Key key, StrongPtr value, bool prune=true);
/// Retrieves the item associated with the key. /// Retrieves the item associated with the key.
/// \return An item or null. /// \return An item or null.
@ -39,14 +41,19 @@ namespace cache
iterator begin(); iterator begin();
iterator end(); iterator end();
/// Removes known invalid entries
void prune();
private: private:
Map mData; Map mData;
std::vector<Key> mDirty;
}; };
template <typename Key, typename T> template <typename Key, typename T>
WeakCache<Key, T>::iterator::iterator(typename Map::iterator current, typename Map::iterator end) WeakCache<Key, T>::iterator::iterator(WeakCache* cache, typename Map::iterator current, typename Map::iterator end)
: mCurrent(current) : mCache(cache)
, mCurrent(current)
, mEnd(end) , mEnd(end)
{ {
// Move to 1st available valid item // Move to 1st available valid item
@ -54,6 +61,7 @@ namespace cache
{ {
mPtr = mCurrent->second.lock(); mPtr = mCurrent->second.lock();
if (mPtr) break; if (mPtr) break;
else mCache->mDirty.push_back(mCurrent->first);
} }
} }
@ -62,7 +70,7 @@ namespace cache
{ {
auto next = mCurrent; auto next = mCurrent;
++next; ++next;
return *this = iterator(next, mEnd); return *this = iterator(mCache, next, mEnd);
} }
template <typename Key, typename T> template <typename Key, typename T>
@ -85,9 +93,10 @@ namespace cache
template <typename Key, typename T> template <typename Key, typename T>
void WeakCache<Key, T>::insert(Key key, StrongPtr value) void WeakCache<Key, T>::insert(Key key, StrongPtr value, bool shouldPrune)
{ {
mData[key] = WeakPtr(value); mData[key] = WeakPtr(value);
if (shouldPrune) prune();
} }
template <typename Key, typename T> template <typename Key, typename T>
@ -103,13 +112,26 @@ namespace cache
template <typename Key, typename T> template <typename Key, typename T>
typename WeakCache<Key, T>::iterator WeakCache<Key, T>::begin() typename WeakCache<Key, T>::iterator WeakCache<Key, T>::begin()
{ {
return iterator(mData.begin(), mData.end()); return iterator(this, mData.begin(), mData.end());
} }
template <typename Key, typename T> template <typename Key, typename T>
typename WeakCache<Key, T>::iterator WeakCache<Key, T>::end() typename WeakCache<Key, T>::iterator WeakCache<Key, T>::end()
{ {
return iterator(mData.end(), mData.end()); return iterator(this, mData.end(), mData.end());
}
template <typename Key, typename T>
void WeakCache<Key, T>::prune()
{
// Remove empty entries
for (auto& key : mDirty)
{
auto it = mData.find(key);
if (it != mData.end() && it->second.use_count() == 0)
mData.erase(it);
}
mDirty.clear();
} }
} }

Loading…
Cancel
Save