#ifndef __TclObjCache_h_ #define __TclObjCache_h_ #include #include #include #include "../shared/TclUtil.h" #include "../shared/ThreadMonitor.h" /* Don't convert from strings to objects any more than we have to. This is * especially useful for scripts which are compiled. But it could apply to * data objects, too. * * It's hard to do this in any smart way. Objects cannot be shared between * threads. Threads are pooled, so work may be sent from one thread to the * next at any time. When we save a data value, we have no idea if it will * be read back by this thread or another. When we know we are done with a * script, we have no convenient way to notify all threads that we are done * with it. * * Thought for the future, not urgent: * Many data objects will be stored in the database. The database does not * give us Tcl objects. If we were smart, we could probably recreate these * efficiently without caching. Ideally we'd use the mysql commands which * return integers and doubles in their native form, rather than as strings. * * http://dev.mysql.com/doc/refman/5.5/en/mysql-stmt-fetch.html#id1363684 */ class TclObjCache : private ThreadMonitor::Extra, NoCopy, NoAssign { private: const size_t _maxCacheSize; // _hot contains all cached items that we have used recently. _cold contains // items that might or might not have been used recently. Some keys may be // in both maps; in that case they will both point to the same value so it // doesn't matter which we use. When it's time to clear old values from the // cache, _cold gets emptied, then we move everything from _hot to _cold, // leaving _hot empty. std::map< std::string, TclObjHolder > _hot, _cold; TclObjCache(); bool cacheDisabled() const { return _maxCacheSize == 0; } void clearOldValues(); static TclObjHolder create(std::string const &asString); // from ThreadMonitor::Extra virtual std::string getInfoForThreadMonitor(); public: ~TclObjCache(); TclObjHolder find(std::string const &asString); static TclObjCache &getInstance(); }; #endif