diff --git a/src/cpp/ripple/TaggedCache.h b/src/cpp/ripple/TaggedCache.h index 5d24ce68ee..60ee849fed 100644 --- a/src/cpp/ripple/TaggedCache.h +++ b/src/cpp/ripple/TaggedCache.h @@ -31,6 +31,8 @@ public: typedef boost::weak_ptr weak_data_ptr; typedef boost::shared_ptr data_ptr; + typedef bool (*visitor_func)(const c_Key&, c_Data&); + protected: typedef std::pair cache_entry; @@ -43,7 +45,7 @@ protected: mutable boost::recursive_mutex mLock; std::string mName; // Used for logging - int mTargetSize; // Desired number of cache entries + int mTargetSize; // Desired number of cache entries (0 = ignore) int mTargetAge; // Desired maximum cache age cache_type mCache; // Hold strong reference to recent objects @@ -64,6 +66,8 @@ public: void setTargetSize(int size); void setTargetAge(int age); void sweep(); + void visitAll(visitor_func); // Visits all tracked objects, removes selected objects + void visitCached(visitor_func); // Visits all cached objects, uncaches selected objects bool touch(const key_type& key); bool del(const key_type& key, bool valid); @@ -108,16 +112,19 @@ template void TaggedCache::sweep // Pass 1, remove old objects from cache int cacheRemovals = 0; - cache_iterator cit = mCache.begin(); - while (cit != mCache.end()) + if ((mTargetSize == 0) || (mCache.size() > mTargetSize)) { - if (cit->second.first < target) + cache_iterator cit = mCache.begin(); + while (cit != mCache.end()) { - ++cacheRemovals; - mCache.erase(cit++); + if (cit->second.first < target) + { + ++cacheRemovals; + mCache.erase(cit++); + } + else + ++cit; } - else - ++cit; } // Pass 2, remove dead objects from map @@ -139,6 +146,40 @@ template void TaggedCache::sweep ", map = " << mMap.size() << "-" << mapRemovals; } +template void TaggedCache::visitAll(visitor_func func) +{ // Visits all tracked objects, removes selected objects + boost::recursive_mutex::scoped_lock sl(mLock); + + map_iterator mit = mMap.begin(); + while (mit != mMap.end()) + { + data_ptr cachedData = mit->second.lock(); + if (!cachedData) + mMap.erase(mit++); // dead reference found + else if (func(mit->first, mit->second)) + { + mCache.erase(mit->first); + mMap.erase(mit++); + } + else + ++mit; + } +} + +template void TaggedCache::visitCached(visitor_func func) +{ // Visits all cached objects, uncaches selected objects + boost::recursive_mutex::scoped_lock sl(mLock); + + cache_iterator cit = mCache.begin(); + while (cit != mCache.end()) + { + if (func(cit->first, cit->second.second)) + mCache.erase(cit++); + else + ++cit; + } +} + template bool TaggedCache::touch(const key_type& key) { // If present, make current in cache boost::recursive_mutex::scoped_lock sl(mLock);