#include "mars_debug.h" #include namespace mars { ThreadingModelManager gtmm_ThreadingModelManager; ThreadingModelMonitor::ThreadingModelMonitor( const char * szFuncName, const void * oInst, const ThreadingModel entmThreadingModel ) : _entmThreadingModel(entmThreadingModel), _idThread(boost::this_thread::get_id()), _szFuncName(szFuncName), _pInst(oInst) { if (_entmThreadingModel == ThrMdl_Main) assert(gtmm_ThreadingModelManager.checkMainThread(szFuncName) && "Only the MAIN thread may enter this block"); else { const size_t nRefCount = gtmm_ThreadingModelManager.registerThread(szFuncName, oInst); if (nRefCount > 1 && _entmThreadingModel == ThrMdl_Single) assert(_entmThreadingModel == ThrMdl_Any && "Threading model is SINGLE but this method is not synchronized"); } } ThreadingModelMonitor::~ThreadingModelMonitor() { if (_entmThreadingModel != ThrMdl_Main) { const size_t nRefCount = gtmm_ThreadingModelManager.deregisterThread(_szFuncName, _pInst); assert(nRefCount == 0 || _entmThreadingModel == ThrMdl_Any && "Threading model is SINGLE or MAIN but this method is not synchronized"); } } void ThreadingModelManager::registerMainThread() { { boost::mutex::scoped_lock lock(_mtxMutex); assert(!_bMainThreadSet && "Main thread already registered"); _idMainThread = boost::this_thread::get_id(); _bMainThreadSet = true; } } bool ThreadingModelManager::checkMainThread( const char * szFuncName ) { { boost::mutex::scoped_lock lock(_mtxMutex); return _bMainThreadSet && boost::this_thread::get_id() == _idMainThread && _mapThreadTracker.find(szFuncName) == _mapThreadTracker.end(); } } size_t ThreadingModelManager::registerThread (const char * szFuncName, const void * pThis) { { boost::mutex::scoped_lock lock(_mtxMutex); ThreadConcurrencyMap::iterator i = _mapThreadTracker.find(szFuncName); if (i == _mapThreadTracker.end()) i = _mapThreadTracker.insert(_mapThreadTracker.begin(), std::pair< std::string, ThreadIDSet > (szFuncName, ThreadIDSet())); i->second.insert(boost::this_thread::get_id()); std::pair< const char *, const void * > hCallHandle(szFuncName, pThis); ThreadReferenceCountMap::iterator j = _mapRefCounter.find(hCallHandle); if (j == _mapRefCounter.end()) return _mapRefCounter[hCallHandle] = 1; else { return ++j->second; } } } size_t ThreadingModelManager::deregisterThread(const char * szFuncName, const void * pThis) { { boost::mutex::scoped_lock lock(_mtxMutex); std::pair< const char *, const void * > hCallHandle(szFuncName, pThis); ThreadReferenceCountMap::iterator j = _mapRefCounter.find(hCallHandle); if (j == _mapRefCounter.end()) assert(j != _mapRefCounter.end() && "Impossible, no reference encountered in DTOR"); else { const size_t nRef = --j->second; if (nRef == 0) _mapRefCounter.erase(j); return nRef; } return 0; } } ThreadingModelManager::ThreadingModelManager() : _bMainThreadSet(false) {} }