Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
3.8 kB · 140 lines
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141#ifndef OPENMW_COMPONENTS_WEAKCACHE_HPP#define OPENMW_COMPONENTS_WEAKCACHE_HPP
#include <memory>#include <unordered_map>#include <vector>
namespace Misc{ /// \class WeakCache /// Provides a container to weakly store pointers to shared data. template <typename Key, typename T> class WeakCache { public: using WeakPtr = std::weak_ptr<T>; using StrongPtr = std::shared_ptr<T>; using Map = std::unordered_map<Key, WeakPtr>;
class iterator { public: iterator(WeakCache* cache, typename Map::iterator current, typename Map::iterator end); iterator& operator++(); bool operator==(const iterator& other) const; bool operator!=(const iterator& other) const; StrongPtr operator*();
private: WeakCache* mCache; typename Map::iterator mCurrent, mEnd; StrongPtr mPtr; };
/// Stores a weak pointer to the item. void insert(Key key, StrongPtr value, bool prune = true);
/// Retrieves the item associated with the key. /// \return An item or null. StrongPtr get(Key key);
iterator begin(); iterator end();
/// Removes known invalid entries void prune();
private: Map mData; std::vector<Key> mDirty; };
template <typename Key, typename T> WeakCache<Key, T>::iterator::iterator(WeakCache* cache, typename Map::iterator current, typename Map::iterator end) : mCache(cache) , mCurrent(current) , mEnd(end) { // Move to 1st available valid item for (; mCurrent != mEnd; ++mCurrent) { mPtr = mCurrent->second.lock(); if (mPtr) break; else mCache->mDirty.push_back(mCurrent->first); } }
template <typename Key, typename T> typename WeakCache<Key, T>::iterator& WeakCache<Key, T>::iterator::operator++() { auto next = mCurrent; ++next; return *this = iterator(mCache, next, mEnd); }
template <typename Key, typename T> bool WeakCache<Key, T>::iterator::operator==(const iterator& other) const { return mCurrent == other.mCurrent; }
template <typename Key, typename T> bool WeakCache<Key, T>::iterator::operator!=(const iterator& other) const { return !(*this == other); }
template <typename Key, typename T> typename WeakCache<Key, T>::StrongPtr WeakCache<Key, T>::iterator::operator*() { return mPtr; }
template <typename Key, typename T> void WeakCache<Key, T>::insert(Key key, StrongPtr value, bool shouldPrune) { mData[key] = WeakPtr(value); if (shouldPrune) prune(); }
template <typename Key, typename T> typename WeakCache<Key, T>::StrongPtr WeakCache<Key, T>::get(Key key) { auto searchIt = mData.find(key); if (searchIt != mData.end()) return searchIt->second.lock(); else return StrongPtr(); }
template <typename Key, typename T> typename WeakCache<Key, T>::iterator WeakCache<Key, T>::begin() { return iterator(this, mData.begin(), mData.end()); }
template <typename Key, typename T> typename WeakCache<Key, T>::iterator WeakCache<Key, T>::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(); }}
#endif