#include "../shared/ThreadMonitor.h" #include "../shared/ContainerThread.h" #include "AutoSymbolList.h" // Make these names explicit. This function will likely be run in the batch // thread, along with other tasks. static const std::string s_RELOAD_SYMBOL_LIST = "reload_symbol_list"; static const std::string s_RELEASE_SYMBOL_LIST = "release_symbol_list"; static const std::string s_CREATE_SYMBOL_LIST = "create_symbol_list"; class AutoSymbolListManagerImpl : public AutoSymbolListManager, public ForeverThreadUser { private: typedef std::multimap< time_t, AutoSymbolList::Description > ByTime; ByTime _byTime; void addToSchedule(AutoSymbolList::Description const &description) { _byTime.insert(ByTime::value_type(time(NULL)+60, description)); } public: AutoSymbolListManagerImpl() : ForeverThreadUser(IContainerThread::batch()) { assert(!_instance); _instance = this; start(); } virtual void add(AutoSymbolList::Description const &description) { class W : public IContainerThread::Work { public: AutoSymbolList::Description description; AutoSymbolListManagerImpl *This; virtual void inThread() { This->addToSchedule(description); ThreadMonitor::find().increment(s_CREATE_SYMBOL_LIST); } }; W *work = new W; work->description = description; work->This = this; getContainer()->addToQueue(work); } virtual void beforeSleep(IBeforeSleepCallbacks &callbacks) { if (_byTime.empty()) return; const time_t now = time(NULL); ByTime::iterator nextItem = _byTime.begin(); time_t nextTime = nextItem->first; if (nextTime <= now) { // The first item is ready. Execute it. AutoSymbolList::Description const &description = nextItem->second; if (AutoSymbolList::reloadOrRelease(description)) { ThreadMonitor::find().increment(s_RELOAD_SYMBOL_LIST); addToSchedule(description); } else ThreadMonitor::find().increment(s_RELEASE_SYMBOL_LIST); // And remove the item we just executed. _byTime.erase(nextItem); // Sleep based on the following item, not the one we just processed. if (_byTime.empty()) return; nextItem = _byTime.begin(); nextTime = nextItem->first; } // Yield after processing at most one item. If more items are ready now, // we will ask to be woken as soon as the rest of the queue has been // processed. callbacks.wakeAfterMs((nextTime - now) * 1000); } }; void initAutoSymbolListScheduler() { new AutoSymbolListManagerImpl(); }