From efe13d7621dc28e5652d68a1d7ee578bef07275b Mon Sep 17 00:00:00 2001 From: "wrenczes@gmail.com" Date: Sun, 3 Apr 2011 07:19:01 +0000 Subject: [PATCH] Checkpoint - refactored out my ThreadedCardRetriever code into a separate header. This header isn't included by anyone else for the moment, so it currently has no impact on the build. --- projects/mtg/include/CacheEngine.h | 150 +++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 projects/mtg/include/CacheEngine.h diff --git a/projects/mtg/include/CacheEngine.h b/projects/mtg/include/CacheEngine.h new file mode 100644 index 000000000..959c6dcb9 --- /dev/null +++ b/projects/mtg/include/CacheEngine.h @@ -0,0 +1,150 @@ +#include "PrecompiledHeader.h" + +#include "Threading.h" +#include +#include + + +struct CacheRequest +{ + CacheRequest() + { + } + + CacheRequest(std::string inFilename, int inSubmode, int inCacheID) + : filename(inFilename), submode(inSubmode), cacheID(inCacheID) + { + } + + std::string filename; + int submode; + int cacheID; +}; + +const boost::posix_time::milliseconds kIdleTime(100); + + +class ThreadedCardRetriever +{ +public: + + static void Create(WCache& inCache) + { + LOG("Creating ThreadedCardRetriever"); + sInstance = NEW ThreadedCardRetriever(inCache); + sInstance->StartProcessing(); + } + + static ThreadedCardRetriever* Instance() + { + return sInstance; + } + + static void Terminate() + { + SAFE_DELETE(sInstance); + } + + ThreadedCardRetriever(WCache& inCache) + : mTextureCache(inCache), mProcessing(true) + { + } + + ~ThreadedCardRetriever() + { + StopProcessing(); + mWorkerThread.join(); + } + + void QueueRequest(const std::string& inFilePath, int inSubmode, int inCacheID) + { + boost::mutex::scoped_lock lock(mMutex); + // mRequestLookup is used to prevent duplicate requests for the same id + if (mRequestLookup.find(inCacheID) == mRequestLookup.end() && mTextureCache.cache.find(inCacheID) == mTextureCache.cache.end()) + { +#ifdef DOLOG + std::ostringstream stream; + stream << "Queueing request: " << inFilePath; + LOG(stream.str().c_str()); +#endif + mRequestLookup.insert(inCacheID); + mRequestQueue.push(CacheRequest(inFilePath, inSubmode, inCacheID)); + + // capping the number of queued decodes to 7, as this is + // the maximum # of cards we display concurrently in the deck editor. + if (mRequestQueue.size() > 7) + { + int cacheIDToRemove; + while (mRequestQueue.size() > 7) + { + // pop the older requests out of the queue + cacheIDToRemove = mRequestQueue.front().cacheID; + mRequestQueue.pop(); + mRequestLookup.erase(cacheIDToRemove); + + assert(mRequestLookup.size() - mRequestQueue.size() < 2); + } + } + } + } + +protected: + ThreadedCardRetriever(); + + static void ThreadProc(void* inParam) + { + LOG("Entering ThreadedCardRetriever::ThreadProc"); + ThreadedCardRetriever* instance = reinterpret_cast(inParam); + if (instance) + { + while (instance->mProcessing) + { + while (!instance->mRequestQueue.empty()) + { + CacheRequest request; + { + boost::mutex::scoped_lock lock(instance->mMutex); + request = instance->mRequestQueue.front(); + instance->mRequestQueue.pop(); + } + + instance->mTextureCache.LoadIntoCache(request.cacheID, request.filename, request.submode); + + { + boost::mutex::scoped_lock lock(instance->mMutex); + instance->mRequestLookup.erase(request.cacheID); + } + + // not sure this is necessary, adding it to potentially prevent SIGHUP on the psp + // rumour has it that if a worker thread doesn't allow the main thread a chance to run, it can hang the unit + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + } + + boost::this_thread::sleep(kIdleTime); + } + } + } + + void StartProcessing() + { + mWorkerThread = boost::thread(ThreadProc, this); + } + + void StopProcessing() + { + LOG("StopProcessing called"); + mProcessing = false; + } + + WCache& mTextureCache; + boost::thread mWorkerThread; + + std::queue mRequestQueue; + std::set mRequestLookup; + boost::mutex mMutex; + volatile bool mProcessing; + + static ThreadedCardRetriever* sInstance; +}; + +ThreadedCardRetriever* ThreadedCardRetriever::sInstance = NULL; \ No newline at end of file