Added better control for cancel GraphicsThreads.

This commit is contained in:
Robert Osfield 2005-11-10 15:25:06 +00:00
parent b19c005178
commit c2f1527fe0
3 changed files with 172 additions and 39 deletions

View File

@ -90,6 +90,22 @@ struct DrawOperation : public osg::GraphicsThread::Operation
osg::ref_ptr<osgUtil::SceneView> _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<osgUtil::SceneView> _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"<<std::endl;
// start clean up.
for(gitr = graphicsContextSet.begin();
gitr != graphicsContextSet.end();
++gitr)
{
osg::GraphicsContext* context = *gitr;
osg::GraphicsThread* thread = context->getGraphicsThread();
if (thread)
{
thread->removeAllOperations();
thread->setDone(true);
}
}
std::cout<<"Removed all operations"<<std::endl;
return 0;
}

View File

@ -100,6 +100,9 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread
/** Get whether the operation should be kept once its been applied.*/
bool getKeep() const { return _keep; }
/** if this operation is a barrier then release it.*/
virtual void release() {}
/** Do the actual task of this operation.*/
virtual void operator () (GraphicsContext*) {}
@ -111,9 +114,24 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread
* executed by the graphics thread once this operation gets to the head of the queue.*/
void add(Operation* operation, bool waitForCompletion=false);
/** Remove operation from OperationQueue.*/
void remove(Operation* operation);
/** Remove named operation from OperationQueue.*/
void remove(const std::string& name);
/** Remove all operations from OperationQueue.*/
void removeAllOperations();
/** Get the operation currently being run.*/
osg::ref_ptr<Operation> 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<osg::Block> _operationsBlock;
OperationQueue _operations;
osg::ref_ptr<Operation> _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);
};

View File

@ -25,25 +25,25 @@ struct ThreadExitTidyUp
_context(context),
_closeContextOnExit(closeContextOnExit)
{
osg::notify(osg::NOTICE)<<"starting thread context "<<_context<<std::endl;
osg::notify(osg::INFO)<<"starting thread context "<<_context<<std::endl;
}
~ThreadExitTidyUp()
{
osg::notify(osg::NOTICE)<<"exit thread"<<std::endl;
osg::notify(osg::INFO)<<"exit thread"<<std::endl;
if (_context)
{
if (_closeContextOnExit)
{
osg::notify(osg::NOTICE)<<" - close context "<<_context<<std::endl;
osg::notify(osg::INFO)<<" - close context "<<_context<<std::endl;
_context->closeImplementation();
osg::notify(osg::NOTICE)<<" - done close context "<<_context<<std::endl;
osg::notify(osg::INFO)<<" - done close context "<<_context<<std::endl;
}
else
{
osg::notify(osg::NOTICE)<<" - releaseContext "<<_context<<std::endl;
osg::notify(osg::INFO)<<" - releaseContext "<<_context<<std::endl;
//_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 "<<this<<std::endl;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
if (_currentOperation.valid())
{
osg::notify(osg::INFO)<<"releasing "<<_currentOperation.get()<<std::endl;
_currentOperation->release();
}
}
_operationsBlock->release();
}
}
int GraphicsThread::cancel()
{
osg::notify(osg::INFO)<<"Cancelling graphics thread "<<this<<std::endl;
@ -102,37 +131,28 @@ int GraphicsThread::cancel()
itr != _operations.end();
++itr)
{
BarrierOperation* barrier = dynamic_cast<BarrierOperation*>(itr->get());
if (barrier)
{
barrier->release();
//barrier->invalidate();
osg::notify(osg::INFO)<<" Invalidating barrier "<<this<<std::endl;
}
(*itr)->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<BarrierOperation*>(itr->get());
if (barrier)
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
for(OperationQueue::iterator itr = _operations.begin();
itr != _operations.end();
++itr)
{
barrier->release();
//barrier->invalidate();
osg::notify(osg::INFO)<<" Invalidating barrier "<<this<<std::endl;
(*itr)->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"<<std::endl;
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> 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"<<std::endl;
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> 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"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> 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"<<std::endl;
osg::notify(osg::INFO)<<"In main loop "<<this<<std::endl;
if (_operations.empty())
{
_operationsBlock->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"<<std::endl;
osg::notify(osg::INFO)<<"get op "<<_done<<" "<<this<<std::endl;
ref_ptr<Operation> operation;
// get the front of the file request list.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
if (!_operations.empty())
{
// get the next item
operation = *itr;
_currentOperation = *itr;
if (!operation->getKeep())
if (!_currentOperation->getKeep())
{
osg::notify(osg::INFO)<<"removing "<<operation->getName()<<std::endl;
osg::notify(osg::INFO)<<"removing "<<_currentOperation->getName()<<std::endl;
// remove it from the opeations queue
itr = _operations.erase(itr);
@ -244,7 +305,7 @@ void GraphicsThread::run()
}
else
{
osg::notify(osg::INFO)<<"increment "<<operation->getName()<<std::endl;
osg::notify(osg::INFO)<<"increment "<<_currentOperation->getName()<<std::endl;
// move on to the next operation in the list.
++itr;
@ -255,12 +316,17 @@ void GraphicsThread::run()
}
if (operation.valid())
if (_currentOperation.valid())
{
osg::notify(osg::INFO)<<"Doing op "<<operation->getName()<<" "<<this<<std::endl;
osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;
// call the graphics operation.
(*operation)(_graphicsContext);
(*_currentOperation)(_graphicsContext);
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_currentOperation = 0;
}
}
if (firstTime)
@ -273,7 +339,7 @@ void GraphicsThread::run()
} while (!testCancel() && !_done);
osg::notify(osg::NOTICE)<<"exit loop"<<std::endl;
osg::notify(osg::INFO)<<"exit loop "<<this<<std::endl;
}
@ -285,6 +351,11 @@ void SwapBuffersOperation::operator () (GraphicsContext* context)
}
}
void BarrierOperation::release()
{
Barrier::release();
}
void BarrierOperation::operator () (GraphicsContext*)
{
if (_preBlockOp==GL_FLUSH) glFlush();
@ -293,6 +364,12 @@ void BarrierOperation::operator () (GraphicsContext*)
block();
}
void ReleaseContext_Block_MakeCurrentOperation::release()
{
Block::release();
}
void ReleaseContext_Block_MakeCurrentOperation::operator () (GraphicsContext* context)
{
if (!context) return;