#include "../shared/MiscSupport.h" #include "../shared/ThreadClass.h" #include "../shared/GlobalConfigFile.h" #include "TclObjCache.h" std::string TclObjCache::getInfoForThreadMonitor() { TclList result; result<<"TclObjCache"<<"cold count"<<_cold.size()<<"hot count"<<_hot.size(); return result; } TclObjCache::TclObjCache() : _maxCacheSize(strtolDefault(getConfigItem("max_tcl_obj_cache_size"), 250)) { ThreadMonitor::find().add(this); } TclObjCache::~TclObjCache() { assert(false && "There is no way to undo ThreadMonitor::find().add()"); } TclObjHolder TclObjCache::create(std::string const &asString) { return Tcl_NewStringObj(asString.data(), asString.size()); } static const std::string s_clearOldValues = "TclObjCache::clearOldValues"; void TclObjCache::clearOldValues() { ThreadMonitor::find().increment(s_clearOldValues); _cold.clear(); _cold.swap(_hot); // Final state: _hot is now empty. _cold contains exactly what was // previously in _hot. } TclObjHolder TclObjCache::find(std::string const &asString) { if (cacheDisabled()) return create(asString); TclObjHolder &inHot = _hot[asString]; bool hotChanged = false; if (!inHot) { hotChanged = true; if (TclObjHolder *inCold = getProperty(_cold, asString)) // Found in _cold. Add it to _hot so we won't delete it any time soon. // Leave a copy in _cold for simplicity. inHot = *inCold; else // Not found. Create it and add it to _hot. inHot = create(asString); } // Save a copy of this value because the reference might be invalidated // before we need the value. TclObjHolder result = inHot; if (hotChanged && (_hot.size() >= _maxCacheSize)) clearOldValues(); return result; } TclObjCache &TclObjCache::getInstance() { static __thread TclObjCache *instance = NULL; if (!instance) instance = new TclObjCache; return *instance; }