From b7a548923c43b244a2065bcf99951c598320f28b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 12 Jun 2008 16:33:24 +0000 Subject: [PATCH] Refactored the management of the request queues so that the appropraite mutex is locked when DatabaseRequest objects are modified --- src/osgDB/DatabasePager.cpp | 154 ++++++++++++++++++++++++------------ 1 file changed, 103 insertions(+), 51 deletions(-) diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index ec4c414c3..0a36daa13 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -238,32 +238,42 @@ public: ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// // -// RequestQueue +// ReadQueue // -DatabasePager::RequestQueue::RequestQueue(DatabasePager* pager, const std::string& name): +DatabasePager::ReadQueue::ReadQueue(DatabasePager* pager, const std::string& name): _pager(pager), _name(name) { _block = new osg::RefBlock; } -void DatabasePager::RequestQueue::clear() +void DatabasePager::ReadQueue::clear() { OpenThreads::ScopedLock lock(_requestMutex); + + for(RequestList::iterator citr = _requestList.begin(); + citr != _requestList.end(); + ++citr) + { + (*citr)->_loadedModel = 0; + (*citr)->_requestQueue = 0; + } + _requestList.clear(); updateBlock(); } -void DatabasePager::RequestQueue::add(DatabasePager::DatabaseRequest* databaseRequest) +void DatabasePager::ReadQueue::add(DatabasePager::DatabaseRequest* databaseRequest) { OpenThreads::ScopedLock lock(_requestMutex); _requestList.push_back(databaseRequest); + databaseRequest->_requestQueue = this; updateBlock(); } -void DatabasePager::RequestQueue::takeFirst(osg::ref_ptr& databaseRequest) +void DatabasePager::ReadQueue::takeFirst(osg::ref_ptr& databaseRequest) { OpenThreads::ScopedLock lock(_requestMutex); @@ -271,6 +281,7 @@ void DatabasePager::RequestQueue::takeFirst(osg::ref_ptr& datab { _requestList.sort(SortFileRequestFunctor()); databaseRequest = _requestList.front(); + databaseRequest->_requestQueue = 0; _requestList.erase(_requestList.begin()); updateBlock(); @@ -364,8 +375,8 @@ void DatabasePager::DatabaseThread::run() bool firstTime = true; - osg::ref_ptr read_queue; - osg::ref_ptr out_queue; + osg::ref_ptr read_queue; + osg::ref_ptr out_queue; switch(_mode) { @@ -630,13 +641,15 @@ void DatabasePager::DatabaseThread::run() { if (loadedObjectsNeedToBeCompiled) { - OpenThreads::ScopedLock lock(_pager->_dataToCompileListMutex); - _pager->_dataToCompileList.push_back(databaseRequest); + OpenThreads::ScopedLock lock(_pager->_dataToCompileList->_requestMutex); + databaseRequest->_requestQueue = _pager->_dataToCompileList.get(); + _pager->_dataToCompileList->_requestList.push_back(databaseRequest); } else { - OpenThreads::ScopedLock lock(_pager->_dataToMergeListMutex); - _pager->_dataToMergeList.push_back(databaseRequest); + OpenThreads::ScopedLock lock(_pager->_dataToMergeList->_requestMutex); + databaseRequest->_requestQueue = _pager->_dataToMergeList.get(); + _pager->_dataToMergeList->_requestList.push_back(databaseRequest); } } @@ -645,28 +658,29 @@ void DatabasePager::DatabaseThread::run() // graphics context thread(s). if (loadedObjectsNeedToBeCompiled) { - OpenThreads::ScopedLock lock(_pager->_dataToCompileListMutex); - _pager->_dataToCompileList.sort(SortFileRequestFunctor()); + OpenThreads::ScopedLock lock(_pager->_dataToCompileList->_requestMutex); + _pager->_dataToCompileList->_requestList.sort(SortFileRequestFunctor()); // Prune all the old entries. - DatabaseRequestList::iterator tooOld - = std::find_if(_pager->_dataToCompileList.begin(), - _pager->_dataToCompileList.end(), + RequestQueue::RequestList::iterator tooOld + = std::find_if(_pager->_dataToCompileList->_requestList.begin(), + _pager->_dataToCompileList->_requestList.end(), refPtrAdapt(std::not1(std::bind2nd(std::mem_fun(&DatabaseRequest::isRequestCurrent), _pager->_frameNumber)))); // This is the database thread, so just delete - for(DatabaseRequestList::iterator citr = tooOld; - citr != _pager->_dataToCompileList.end(); + for(RequestQueue::RequestList::iterator citr = tooOld; + citr != _pager->_dataToCompileList->_requestList.end(); ++citr) { osg::notify(osg::INFO)<<_name<<": pruning from compile list"<_loadedModel = 0; + (*citr)->_requestQueue = 0; } - _pager->_dataToCompileList.erase(tooOld, _pager->_dataToCompileList.end()); + _pager->_dataToCompileList->_requestList.erase(tooOld, _pager->_dataToCompileList->_requestList.end()); - loadedObjectsNeedToBeCompiled = !_pager->_dataToCompileList.empty(); + loadedObjectsNeedToBeCompiled = !_pager->_dataToCompileList->_requestList.empty(); } if (loadedObjectsNeedToBeCompiled && !_pager->_activeGraphicsContexts.empty()) @@ -845,8 +859,12 @@ DatabasePager::DatabasePager() //if (osgDB::Registry::instance()->getSharedStateManager()) //osgDB::Registry::instance()->setUseObjectCacheHint(true); - _fileRequestQueue = new RequestQueue(this,"fileRequestQueue"); - _httpRequestQueue = new RequestQueue(this,"httpRequestQueue"); + _fileRequestQueue = new ReadQueue(this,"fileRequestQueue"); + _httpRequestQueue = new ReadQueue(this,"httpRequestQueue"); + + _dataToCompileList = new RequestQueue; + _dataToMergeList = new RequestQueue; + #if 0 _databaseThreads.push_back(new DatabaseThread(this, DatabaseThread::HANDLE_ALL_REQUESTS,"HANDLE_ALL_REQUESTS")); @@ -893,8 +911,11 @@ DatabasePager::DatabasePager(const DatabasePager& rhs) _minimumTimeAvailableForGLCompileAndDeletePerFrame = rhs._minimumTimeAvailableForGLCompileAndDeletePerFrame; _maximumNumOfObjectsToCompilePerFrame = rhs._maximumNumOfObjectsToCompilePerFrame; - _fileRequestQueue = new RequestQueue(this,"fileRequestQueue"); - _httpRequestQueue = new RequestQueue(this,"httpRequestQueue"); + _fileRequestQueue = new ReadQueue(this,"fileRequestQueue"); + _httpRequestQueue = new ReadQueue(this,"httpRequestQueue"); + + _dataToCompileList = new RequestQueue; + _dataToMergeList = new RequestQueue; for(DatabaseThreadList::const_iterator dt_itr = rhs._databaseThreads.begin(); dt_itr != rhs._databaseThreads.end(); @@ -985,13 +1006,27 @@ void DatabasePager::clear() _httpRequestQueue->clear(); { - OpenThreads::ScopedLock lock(_dataToCompileListMutex); - _dataToCompileList.clear(); + OpenThreads::ScopedLock lock(_dataToCompileList->_requestMutex); + for(RequestQueue::RequestList::iterator citr = _dataToCompileList->_requestList.begin(); + citr != _dataToCompileList->_requestList.end(); + ++citr) + { + (*citr)->_loadedModel = 0; + (*citr)->_requestQueue = 0; + } + _dataToCompileList->_requestList.clear(); } { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - _dataToMergeList.clear(); + OpenThreads::ScopedLock lock(_dataToMergeList->_requestMutex); + for(RequestQueue::RequestList::iterator citr = _dataToMergeList->_requestList.begin(); + citr != _dataToMergeList->_requestList.end(); + ++citr) + { + (*citr)->_loadedModel = 0; + (*citr)->_requestQueue = 0; + } + _dataToMergeList->_requestList.clear(); } // note, no need to use a mutex as the list is only accessed from the update thread. @@ -1050,12 +1085,25 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou DatabaseRequest* databaseRequest = dynamic_cast(databaseRequestRef.get()); if (databaseRequest) { - osg::notify(osg::INFO)<<"DatabasePager::fileRquest("<_frameNumberLastRequest = frameNumber; - databaseRequest->_timestampLastRequest = timestamp; - databaseRequest->_priorityLastRequest = priority; - ++(databaseRequest->_numOfRequests); + RequestQueue* requestQueue = databaseRequest->_requestQueue; + if (requestQueue) + { + OpenThreads::ScopedLock lock(requestQueue->_requestMutex); + + databaseRequest->_frameNumberLastRequest = frameNumber; + databaseRequest->_timestampLastRequest = timestamp; + databaseRequest->_priorityLastRequest = priority; + ++(databaseRequest->_numOfRequests); + } + else + { + databaseRequest->_frameNumberLastRequest = frameNumber; + databaseRequest->_timestampLastRequest = timestamp; + databaseRequest->_priorityLastRequest = priority; + ++(databaseRequest->_numOfRequests); + } foundEntry = true; @@ -1071,6 +1119,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou databaseRequest->_priorityLastRequest = priority; databaseRequest->_groupForAddingLoadedSubgraph = group; databaseRequest->_loadOptions = loadOptions; + databaseRequest->_requestQueue = _fileRequestQueue.get(); _fileRequestQueue->add(databaseRequest); } @@ -1099,6 +1148,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou databaseRequest->_priorityLastRequest = priority; databaseRequest->_groupForAddingLoadedSubgraph = group; databaseRequest->_loadOptions = loadOptions; + databaseRequest->_requestQueue = _fileRequestQueue.get(); _fileRequestQueue->_requestList.push_back(databaseRequest.get()); @@ -1157,8 +1207,8 @@ void DatabasePager::setDatabasePagerThreadPause(bool pause) bool DatabasePager::requiresUpdateSceneGraph() const { { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - if (!_dataToMergeList.empty()) return true; + OpenThreads::ScopedLock lock(_dataToMergeList->_requestMutex); + if (!_dataToMergeList->_requestList.empty()) return true; } return false; @@ -1171,16 +1221,16 @@ void DatabasePager::addLoadedDataToSceneGraph(double timeStamp) // osg::Timer_t before = osg::Timer::instance()->tick(); - DatabaseRequestList localFileLoadedList; + RequestQueue::RequestList localFileLoadedList; // get the dat for the _dataToCompileList, leaving it empty via a std::vector<>.swap. { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - localFileLoadedList.swap(_dataToMergeList); + OpenThreads::ScopedLock lock(_dataToMergeList->_requestMutex); + localFileLoadedList.swap(_dataToMergeList->_requestList); } // add the loaded data into the scene graph. - for(DatabaseRequestList::iterator itr=localFileLoadedList.begin(); + for(RequestQueue::RequestList::iterator itr=localFileLoadedList.begin(); itr!=localFileLoadedList.end(); ++itr) { @@ -1360,8 +1410,8 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph) bool DatabasePager::requiresCompileGLObjects() const { - OpenThreads::ScopedLock lock(_dataToCompileListMutex); - return !_dataToCompileList.empty(); + OpenThreads::ScopedLock lock(_dataToCompileList->_requestMutex); + return !_dataToCompileList->_requestList.empty(); } void DatabasePager::setCompileGLObjectsForContextID(unsigned int contextID, bool on) @@ -1433,10 +1483,10 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) // get the first compilable entry. { - OpenThreads::ScopedLock lock(_dataToCompileListMutex); + OpenThreads::ScopedLock lock(_dataToCompileList->_requestMutex); // advance to the next entry to compile if one is available. - databaseRequest = _dataToCompileList.empty() ? 0 : _dataToCompileList.front(); + databaseRequest = _dataToCompileList->_requestList.empty() ? 0 : _dataToCompileList->_requestList.front(); }; unsigned int numObjectsCompiled = 0; @@ -1553,7 +1603,7 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) // osg::notify(osg::NOTICE)<<"All compiled"< lock(_dataToCompileListMutex); + OpenThreads::ScopedLock lock(_dataToCompileList->_requestMutex); // The request might have been removed from the // _dataToCompile list by another graphics thread, in @@ -1563,19 +1613,21 @@ void DatabasePager::compileGLObjects(osg::State& state, double& availableTime) // shuffled by the pager, so the current request is // not guaranteed to still be at the beginning of the // list. - DatabaseRequestList::iterator requestIter - = std::find(_dataToCompileList.begin(), _dataToCompileList.end(), + + RequestQueue::RequestList::iterator requestIter + = std::find(_dataToCompileList->_requestList.begin(), _dataToCompileList->_requestList.end(), databaseRequest); - if (requestIter != _dataToCompileList.end()) + if (requestIter != _dataToCompileList->_requestList.end()) { { - OpenThreads::ScopedLock lock(_dataToMergeListMutex); - _dataToMergeList.push_back(databaseRequest); + OpenThreads::ScopedLock lock(_dataToMergeList->_requestMutex); + databaseRequest->_requestQueue = _dataToMergeList.get(); + _dataToMergeList->_requestList.push_back(databaseRequest); } - _dataToCompileList.erase(requestIter); + _dataToCompileList->_requestList.erase(requestIter); } - if (!_dataToCompileList.empty()) databaseRequest = _dataToCompileList.front(); + if (!_dataToCompileList->_requestList.empty()) databaseRequest = _dataToCompileList->_requestList.front(); else databaseRequest = 0; }