From c2f1527fe07d2b1688d49166b65480b3b18485d2 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 10 Nov 2005 15:25:06 +0000 Subject: [PATCH] Added better control for cancel GraphicsThreads. --- examples/osgcamera/osgcamera.cpp | 33 +++++++ include/osg/GraphicsThread | 23 +++++ src/osg/GraphicsThread.cpp | 155 +++++++++++++++++++++++-------- 3 files changed, 172 insertions(+), 39 deletions(-) diff --git a/examples/osgcamera/osgcamera.cpp b/examples/osgcamera/osgcamera.cpp index b32c66303..5432d878f 100644 --- a/examples/osgcamera/osgcamera.cpp +++ b/examples/osgcamera/osgcamera.cpp @@ -90,6 +90,22 @@ struct DrawOperation : public osg::GraphicsThread::Operation osg::ref_ptr _sceneView; }; +struct CleanUpOperation : public osg::GraphicsThread::Operation +{ + CleanUpOperation(osgUtil::SceneView* sceneView): + osg::GraphicsThread::Operation("CleanUp",false), + _sceneView(sceneView) + { + } + + virtual void operator () (osg::GraphicsContext*) + { + _sceneView->releaseAllGLObjects(); + _sceneView->flushAllDeletedGLObjects(); + } + + osg::ref_ptr _sceneView; +}; // main does the following steps to create a multi-thread, multiple camera/graphics context view of a scene graph. // @@ -346,8 +362,25 @@ int main( int argc, char **argv ) } } + std::cout<<"Exiting application"<getGraphicsThread(); + if (thread) + { + thread->removeAllOperations(); + thread->setDone(true); + } + } + + std::cout<<"Removed all operations"< getCurrentOperation() { return _currentOperation; } + /** Run does the graphics thread run loop.*/ virtual void run(); + void setDone(bool done); + bool getDone() const { return _done; } + /** Cancel this graphics thread.*/ virtual int cancel(); @@ -131,6 +149,7 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread OpenThreads::Mutex _operationsMutex; osg::ref_ptr _operationsBlock; OperationQueue _operations; + osg::ref_ptr _currentOperation; }; @@ -159,6 +178,8 @@ struct OSG_EXPORT BarrierOperation : public GraphicsThread::Operation, public Op OpenThreads::Barrier(numThreads), _preBlockOp(op) {} + virtual void release(); + virtual void operator () (GraphicsContext* context); PreBlockOp _preBlockOp; @@ -171,6 +192,8 @@ struct OSG_EXPORT ReleaseContext_Block_MakeCurrentOperation : public GraphicsThr ReleaseContext_Block_MakeCurrentOperation(): GraphicsThread::Operation("ReleaseContext_Block_MakeCurrent", false) {} + virtual void release(); + virtual void operator () (GraphicsContext* context); }; diff --git a/src/osg/GraphicsThread.cpp b/src/osg/GraphicsThread.cpp index dcf36aaf1..1a92dca92 100644 --- a/src/osg/GraphicsThread.cpp +++ b/src/osg/GraphicsThread.cpp @@ -25,25 +25,25 @@ struct ThreadExitTidyUp _context(context), _closeContextOnExit(closeContextOnExit) { - osg::notify(osg::NOTICE)<<"starting thread context "<<_context<closeImplementation(); - osg::notify(osg::NOTICE)<<" - done close context "<<_context<releaseContext(); } @@ -64,10 +64,15 @@ struct BlockOperation : public GraphicsThread::Operation, public Block reset(); } + virtual void release() + { + Block::release(); + } + virtual void operator () (GraphicsContext*) { glFlush(); - release(); + Block::release(); } }; @@ -86,6 +91,30 @@ GraphicsThread::~GraphicsThread() cancel(); } +void GraphicsThread::setDone(bool done) +{ + if (_done==done) return; + + _done = true; + + if (done) + { + osg::notify(osg::INFO)<<"set done "< lock(_operationsMutex); + if (_currentOperation.valid()) + { + osg::notify(osg::INFO)<<"releasing "<<_currentOperation.get()<release(); + } + } + + _operationsBlock->release(); + } + +} + int GraphicsThread::cancel() { osg::notify(osg::INFO)<<"Cancelling graphics thread "<(itr->get()); - if (barrier) - { - barrier->release(); - //barrier->invalidate(); - osg::notify(osg::INFO)<<" Invalidating barrier "<release(); } - -/* - // cancel the thread.. - result = Thread::cancel(); - //join(); -*/ + // release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation. _operationsBlock->release(); // then wait for the the thread to stop running. while(isRunning()) { - for(OperationQueue::iterator itr = _operations.begin(); - itr != _operations.end(); - ++itr) + _operationsBlock->release(); + { - BarrierOperation* barrier = dynamic_cast(itr->get()); - if (barrier) + OpenThreads::ScopedLock lock(_operationsMutex); + + for(OperationQueue::iterator itr = _operations.begin(); + itr != _operations.end(); + ++itr) { - barrier->release(); - //barrier->invalidate(); - osg::notify(osg::INFO)<<" Invalidating barrier "<release(); } + + if (_currentOperation.valid()) _currentOperation->release(); } // commenting out debug info as it was cashing crash on exit, presumable @@ -174,6 +194,46 @@ void GraphicsThread::add(Operation* operation, bool waitForCompletion) } } +void GraphicsThread::remove(Operation* operation) +{ + osg::notify(osg::INFO)<<"Doing remove operation"< lock(_operationsMutex); + + for(OperationQueue::iterator itr = _operations.begin(); + itr!=_operations.end();) + { + if ((*itr)==operation) itr = _operations.erase(itr); + else ++itr; + } +} + +void GraphicsThread::remove(const std::string& name) +{ + osg::notify(osg::INFO)<<"Doing remove named operation"< lock(_operationsMutex); + + // find the remove all operations with specificed name + for(OperationQueue::iterator itr = _operations.begin(); + itr!=_operations.end();) + { + if ((*itr)->getName()==name) itr = _operations.erase(itr); + else ++itr; + } +} + +void GraphicsThread::removeAllOperations() +{ + osg::notify(osg::INFO)<<"Doing remove all operations"< lock(_operationsMutex); + _operations.clear(); +} + + void GraphicsThread::run() { bool contextRealizedInThisThread = false; @@ -202,12 +262,15 @@ void GraphicsThread::run() do { - osg::notify(osg::INFO)<<"In main loop"<block(); + // exit from loop if _done is set. + if (_done) break; + itr = _operations.begin(); } else @@ -215,21 +278,19 @@ void GraphicsThread::run() if (itr == _operations.end()) itr = _operations.begin(); } - osg::notify(osg::INFO)<<"get op"< operation; - // get the front of the file request list. { OpenThreads::ScopedLock lock(_operationsMutex); if (!_operations.empty()) { // get the next item - operation = *itr; + _currentOperation = *itr; - if (!operation->getKeep()) + if (!_currentOperation->getKeep()) { - osg::notify(osg::INFO)<<"removing "<getName()<getName()<getName()<getName()<getName()<<" "<getName()<<" "< lock(_operationsMutex); + _currentOperation = 0; + } } if (firstTime) @@ -273,7 +339,7 @@ void GraphicsThread::run() } while (!testCancel() && !_done); - osg::notify(osg::NOTICE)<<"exit loop"<