#ifndef OPENMW_COMPONENTS_WEAKCACHE_HPP #define OPENMW_COMPONENTS_WEAKCACHE_HPP #include #include namespace cache { /// \class WeakCache /// Provides a container to weakly store pointers to shared data. template class WeakCache { public: using WeakPtr = std::weak_ptr; using StrongPtr = std::shared_ptr; using Map = std::unordered_map; class iterator { public: iterator(typename Map::iterator current, typename Map::iterator end); iterator& operator++(); bool operator==(const iterator& other); bool operator!=(const iterator& other); StrongPtr operator*(); private: typename Map::iterator mCurrent, mEnd; StrongPtr mPtr; }; /// Stores a weak pointer to the item. void insert(Key key, StrongPtr value); /// Retrieves the item associated with the key. /// \return An item or null. StrongPtr get(Key key); iterator begin(); iterator end(); private: Map mData; }; template WeakCache::iterator::iterator(typename Map::iterator current, typename Map::iterator end) : mCurrent(current) , mEnd(end) { // Move to 1st available valid item for ( ; mCurrent != mEnd; ++mCurrent) { mPtr = mCurrent->second.lock(); if (mPtr) break; } } template typename WeakCache::iterator& WeakCache::iterator::operator++() { auto next = mCurrent; ++next; return *this = iterator(next, mEnd); } template bool WeakCache::iterator::operator==(const iterator& other) { return mCurrent == other.mCurrent; } template bool WeakCache::iterator::operator!=(const iterator& other) { return !(*this == other); } template typename WeakCache::StrongPtr WeakCache::iterator::operator*() { return mPtr; } template void WeakCache::insert(Key key, StrongPtr value) { mData[key] = WeakPtr(value); } template typename WeakCache::StrongPtr WeakCache::get(Key key) { auto searchIt = mData.find(key); if (searchIt != mData.end()) return searchIt->second.lock(); else return StrongPtr(); } template typename WeakCache::iterator WeakCache::begin() { return iterator(mData.begin(), mData.end()); } template typename WeakCache::iterator WeakCache::end() { return iterator(mData.end(), mData.end()); } } #endif