Separated OperationsThread out from the GraphicsThread header and introduced

new OperationQueue class.
This commit is contained in:
Robert Osfield
2007-07-09 19:04:36 +00:00
parent 4d04f3f645
commit 44c07b9fad
14 changed files with 626 additions and 672 deletions

View File

@@ -14,153 +14,10 @@
#ifndef OSG_GRAPHICSTHREAD
#define OSG_GRAPHICSTHREAD 1
#include <osg/observer_ptr>
#include <osg/Object>
#include <OpenThreads/Thread>
#include <OpenThreads/Barrier>
#include <OpenThreads/Condition>
#include <OpenThreads/Block>
#include <list>
#include <osg/OperationsThread>
namespace osg {
class RefBlock: virtual public osg::Referenced, public OpenThreads::Block
{
public:
RefBlock() {}
};
/** Base class for implementing graphics operations.*/
class Operation : virtual public Referenced
{
public:
Operation(const std::string& name, bool keep):
_name(name),
_keep(keep) {}
/** Set the human readable name of the operation.*/
void setName(const std::string& name) { _name = name; }
/** Get the human readable name of the operation.*/
const std::string& getName() const { return _name; }
/** Set whether the operation should be kept once its been applied.*/
void setKeep(bool keep) { _keep = keep; }
/** 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 () (Object*) = 0;
protected:
virtual ~Operation() {}
std::string _name;
bool _keep;
};
class OSG_EXPORT OperationQueue : public Referenced
{
public:
OperationQueue();
RefBlock* getOperationsBlock() { return _operationsBlock.get(); }
const RefBlock* getOperationsBlock() const { return _operationsBlock.get(); }
/** Add operation to end of OperationQueue, this will be
* executed by the operation thread once this operation gets to the head of the queue.*/
void add(Operation* operation);
/** 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();
protected:
virtual ~OperationQueue();
typedef std::list< ref_ptr<Operation> > Operations;
OpenThreads::Mutex _operationsMutex;
osg::ref_ptr<osg::RefBlock> _operationsBlock;
Operations _operations;
};
/** GraphicsThread is a helper class for running OpenGL GraphicsOperation within a single thread assigned to a specific GraphicsContext.*/
class OSG_EXPORT OperationsThread : public Referenced, public OpenThreads::Thread
{
public:
OperationsThread();
void setParent(Object* parent) { _parent = parent; }
Object* getParent() { return _parent.get(); }
const Object* getParent() const { return _parent.get(); }
/** Add operation to end of OperationQueue, this will be
* 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();
protected:
virtual ~OperationsThread();
observer_ptr<Object> _parent;
typedef std::list< ref_ptr<Operation> > Operations;
bool _done;
OpenThreads::Mutex _operationsMutex;
osg::ref_ptr<osg::RefBlock> _operationsBlock;
Operations _operations;
osg::ref_ptr<Operation> _currentOperation;
};
/** SwapBufferOperation calls swap buffers on the GraphicsContext.*/
struct OSG_EXPORT SwapBuffersOperation : public Operation
{
@@ -204,6 +61,15 @@ struct OSG_EXPORT ReleaseContext_Block_MakeCurrentOperation : public Operation,
virtual void operator () (Object* context);
};
struct OSG_EXPORT BlockAndFlushOperation : public Operation, public OpenThreads::Block
{
BlockAndFlushOperation();
virtual void release();
virtual void operator () (Object*);
};
}
#endif

View File

@@ -0,0 +1,173 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#ifndef OSG_OPERATIONSTHREAD
#define OSG_OPERATIONSTHREAD 1
#include <osg/observer_ptr>
#include <osg/Object>
#include <OpenThreads/Thread>
#include <OpenThreads/Barrier>
#include <OpenThreads/Condition>
#include <OpenThreads/Block>
#include <list>
namespace osg {
class RefBlock: virtual public osg::Referenced, public OpenThreads::Block
{
public:
RefBlock() {}
};
/** Base class for implementing graphics operations.*/
class Operation : virtual public Referenced
{
public:
Operation(const std::string& name, bool keep):
_name(name),
_keep(keep) {}
/** Set the human readable name of the operation.*/
void setName(const std::string& name) { _name = name; }
/** Get the human readable name of the operation.*/
const std::string& getName() const { return _name; }
/** Set whether the operation should be kept once its been applied.*/
void setKeep(bool keep) { _keep = keep; }
/** 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 () (Object*) = 0;
protected:
virtual ~Operation() {}
std::string _name;
bool _keep;
};
class OSG_EXPORT OperationQueue : public Referenced
{
public:
OperationQueue();
RefBlock* getOperationsBlock() { return _operationsBlock.get(); }
const RefBlock* getOperationsBlock() const { return _operationsBlock.get(); }
/** Get the next operation from the operation queue.
* Return null ref_ptr<> if no operations are left in queue. */
osg::ref_ptr<Operation> getNextOperation();
/** Add operation to end of OperationQueue, this will be
* executed by the operation thread once this operation gets to the head of the queue.*/
void add(Operation* operation);
/** 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();
/** Call release on all operations. */
void releaseAllOperations();
protected:
virtual ~OperationQueue();
typedef std::list< ref_ptr<Operation> > Operations;
OpenThreads::Mutex _operationsMutex;
osg::ref_ptr<osg::RefBlock> _operationsBlock;
Operations _operations;
Operations::iterator _currentOperationIterator;
};
/** GraphicsThread is a helper class for running OpenGL GraphicsOperation within a single thread assigned to a specific GraphicsContext.*/
class OSG_EXPORT OperationsThread : public Referenced, public OpenThreads::Thread
{
public:
OperationsThread();
void setParent(Object* parent) { _parent = parent; }
Object* getParent() { return _parent.get(); }
const Object* getParent() const { return _parent.get(); }
/** Add operation to end of OperationQueue, this will be
* executed by the graphics thread once this operation gets to the head of the queue.*/
void add(Operation* operation);
/** 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();
protected:
virtual ~OperationsThread();
observer_ptr<Object> _parent;
typedef std::list< ref_ptr<Operation> > Operations;
bool _done;
OpenThreads::Mutex _operationsMutex;
osg::ref_ptr<osg::RefBlock> _operationsBlock;
Operations _operations;
osg::ref_ptr<Operation> _currentOperation;
};
}
#endif

View File

@@ -18,18 +18,12 @@
// include Export simply to disable Visual Studio silly warnings.
#include <osgParticle/Export>
#ifndef __sgi
#include <cstdlib>
#else
#include <stdlib.h>
#endif
#include <osg/Vec2>
#include <osg/Vec3>
#include <osg/Vec4>
//using std::rand;
namespace osgParticle
{

View File

@@ -91,6 +91,7 @@ SET(LIB_PUBLIC_HEADERS
${HEADER_PATH}/Notify
${HEADER_PATH}/Object
${HEADER_PATH}/OccluderNode
${HEADER_PATH}/OperationsThread
${HEADER_PATH}/PagedLOD
${HEADER_PATH}/Plane
${HEADER_PATH}/Point
@@ -245,6 +246,7 @@ ADD_LIBRARY(${LIB_NAME}
Notify.cpp
Object.cpp
OccluderNode.cpp
OperationsThread.cpp
PagedLOD.cpp
Point.cpp
PointSprite.cpp

View File

@@ -39,364 +39,6 @@ struct BlockOperation : public Operation, public Block
}
};
/////////////////////////////////////////////////////////////////////////////
//
// OperationsQueue
//
OperationQueue::OperationQueue()
{
}
OperationQueue::~OperationQueue()
{
}
void OperationQueue::add(Operation* operation)
{
osg::notify(osg::INFO)<<"Doing add"<<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);
// add the operation to the end of the list
_operations.push_back(operation);
_operationsBlock->set(true);
}
}
void OperationQueue::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)==operation) itr = _operations.erase(itr);
else ++itr;
}
}
void OperationQueue::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationQueue::removeAllOperations()
{
osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
/////////////////////////////////////////////////////////////////////////////
//
// OperationsThread
//
OperationsThread::OperationsThread():
_parent(0),
_done(false)
{
_operationsBlock = new RefBlock;
}
OperationsThread::~OperationsThread()
{
//osg::notify(osg::NOTICE)<<"Destructing graphics thread "<<this<<std::endl;
cancel();
//osg::notify(osg::NOTICE)<<"Done Destructing graphics thread "<<this<<std::endl;
}
void OperationsThread::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 OperationsThread::cancel()
{
osg::notify(osg::INFO)<<"Cancelling OperationsThred "<<this<<" isRunning()="<<isRunning()<<std::endl;
int result = 0;
if( isRunning() )
{
_done = true;
osg::notify(osg::INFO)<<" Doing cancel "<<this<<std::endl;
for(Operations::iterator itr = _operations.begin();
itr != _operations.end();
++itr)
{
(*itr)->release();
}
// release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation.
_operationsBlock->release();
// then wait for the the thread to stop running.
while(isRunning())
{
_operationsBlock->release();
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
for(Operations::iterator itr = _operations.begin();
itr != _operations.end();
++itr)
{
(*itr)->release();
}
if (_currentOperation.valid()) _currentOperation->release();
}
// commenting out debug info as it was cashing crash on exit, presumable
// due to osg::notify or std::cout destructing earlier than this destructor.
osg::notify(osg::INFO)<<" Waiting for OperationsThread to cancel "<<this<<std::endl;
OpenThreads::Thread::YieldCurrentThread();
}
}
osg::notify(osg::INFO)<<" OperationsThread::cancel() thread cancelled "<<this<<" isRunning()="<<isRunning()<<std::endl;
return result;
}
void OperationsThread::add(Operation* operation, bool waitForCompletion)
{
osg::notify(osg::INFO)<<"Doing add"<<std::endl;
ref_ptr<BlockOperation> block = 0;
{
// aquire the lock on the operations queue to prevent anyone else for modifying it at the same time
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
// add the operation to the end of the list
_operations.push_back(operation);
if (waitForCompletion)
{
block = new BlockOperation;
_operations.push_back(block.get());
}
_operationsBlock->set(true);
}
if (block.valid())
{
// now we wait till the barrier is joined by the graphics thread.
block->block();
}
}
void OperationsThread::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)==operation) itr = _operations.erase(itr);
else ++itr;
}
}
void OperationsThread::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationsThread::removeAllOperations()
{
osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationsThread::run()
{
// make the graphics context current.
GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
if (graphicsContext)
{
graphicsContext->makeCurrent();
}
osg::notify(osg::INFO)<<"Doing run "<<this<<" isRunning()="<<isRunning()<<std::endl;
bool firstTime = true;
Operations::iterator itr = _operations.begin();
do
{
// osg::notify(osg::NOTICE)<<"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
{
if (itr == _operations.end()) itr = _operations.begin();
}
// osg::notify(osg::INFO)<<"get op "<<_done<<" "<<this<<std::endl;
// get the front of the file request list.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
if (!_operations.empty())
{
// get the next item
_currentOperation = *itr;
if (!_currentOperation->getKeep())
{
// osg::notify(osg::INFO)<<"removing "<<_currentOperation->getName()<<std::endl;
// remove it from the opeations queue
itr = _operations.erase(itr);
// osg::notify(osg::INFO)<<"size "<<_operations.size()<<std::endl;
if (_operations.empty())
{
// osg::notify(osg::INFO)<<"setting block "<<_operations.size()<<std::endl;
_operationsBlock->set(false);
}
}
else
{
// osg::notify(osg::INFO)<<"increment "<<_currentOperation->getName()<<std::endl;
// move on to the next operation in the list.
++itr;
}
}
}
if (_currentOperation.valid())
{
// osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;
// call the graphics operation.
(*_currentOperation)(_parent.get());
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_currentOperation = 0;
}
}
if (firstTime)
{
// do a yield to get round a peculiar thread hang when testCancel() is called
// in certain cirumstances - of which there is no particular pattern.
YieldCurrentThread();
firstTime = false;
}
// osg::notify(osg::NOTICE)<<"operations.size()="<<_operations.size()<<" done="<<_done<<" testCancel()"<<testCancel()<<std::endl;
} while (!testCancel() && !_done);
if (graphicsContext)
{
graphicsContext->releaseContext();
}
osg::notify(osg::INFO)<<"exit loop "<<this<<" isRunning()="<<isRunning()<<std::endl;
}
void SwapBuffersOperation::operator () (Object* object)
{
@@ -444,3 +86,21 @@ void ReleaseContext_Block_MakeCurrentOperation::operator () (Object* object)
// re aquire the graphcis context.
context->makeCurrent();
}
BlockAndFlushOperation::BlockAndFlushOperation():
Operation("Block",false)
{
reset();
}
void BlockAndFlushOperation::release()
{
Block::release();
}
void BlockAndFlushOperation::operator () (Object*)
{
glFlush();
Block::release();
}

View File

@@ -0,0 +1,399 @@
/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
*
* This library is open source and may be redistributed and/or modified under
* the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
* (at your option) any later version. The full license is in LICENSE file
* included with this distribution, and on the openscenegraph.org website.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* OpenSceneGraph Public License for more details.
*/
#include <osg/OperationsThread>
#include <osg/GraphicsContext>
#include <osg/Notify>
using namespace osg;
using namespace OpenThreads;
struct BlockOperation : public Operation, public Block
{
BlockOperation():
Operation("Block",false)
{
reset();
}
virtual void release()
{
Block::release();
}
virtual void operator () (Object*)
{
glFlush();
Block::release();
}
};
/////////////////////////////////////////////////////////////////////////////
//
// OperationsQueue
//
OperationQueue::OperationQueue()
{
_currentOperationIterator = _operations.begin();
_operationsBlock = new RefBlock;
}
OperationQueue::~OperationQueue()
{
}
osg::ref_ptr<Operation> OperationQueue::getNextOperation()
{
return osg::ref_ptr<Operation>();
}
void OperationQueue::add(Operation* operation)
{
osg::notify(osg::INFO)<<"Doing add"<<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);
// add the operation to the end of the list
_operations.push_back(operation);
_operationsBlock->set(true);
}
void OperationQueue::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)==operation) itr = _operations.erase(itr);
else ++itr;
}
}
void OperationQueue::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationQueue::removeAllOperations()
{
osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationQueue::releaseAllOperations()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
for(Operations::iterator itr = _operations.begin();
itr!=_operations.end();
++itr)
{
(*itr)->release();
}
}
/////////////////////////////////////////////////////////////////////////////
//
// OperationsThread
//
OperationsThread::OperationsThread():
_parent(0),
_done(false)
{
_operationsBlock = new RefBlock;
}
OperationsThread::~OperationsThread()
{
//osg::notify(osg::NOTICE)<<"Destructing graphics thread "<<this<<std::endl;
cancel();
//osg::notify(osg::NOTICE)<<"Done Destructing graphics thread "<<this<<std::endl;
}
void OperationsThread::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 OperationsThread::cancel()
{
osg::notify(osg::INFO)<<"Cancelling OperationsThred "<<this<<" isRunning()="<<isRunning()<<std::endl;
int result = 0;
if( isRunning() )
{
_done = true;
osg::notify(osg::INFO)<<" Doing cancel "<<this<<std::endl;
for(Operations::iterator itr = _operations.begin();
itr != _operations.end();
++itr)
{
(*itr)->release();
}
// release the frameBlock and _databasePagerThreadBlock incase its holding up thread cancelation.
_operationsBlock->release();
// then wait for the the thread to stop running.
while(isRunning())
{
_operationsBlock->release();
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
for(Operations::iterator itr = _operations.begin();
itr != _operations.end();
++itr)
{
(*itr)->release();
}
if (_currentOperation.valid()) _currentOperation->release();
}
// commenting out debug info as it was cashing crash on exit, presumable
// due to osg::notify or std::cout destructing earlier than this destructor.
osg::notify(osg::INFO)<<" Waiting for OperationsThread to cancel "<<this<<std::endl;
OpenThreads::Thread::YieldCurrentThread();
}
}
osg::notify(osg::INFO)<<" OperationsThread::cancel() thread cancelled "<<this<<" isRunning()="<<isRunning()<<std::endl;
return result;
}
void OperationsThread::add(Operation* operation)
{
osg::notify(osg::INFO)<<"Doing add"<<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);
// add the operation to the end of the list
_operations.push_back(operation);
_operationsBlock->set(true);
}
void OperationsThread::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)==operation) itr = _operations.erase(itr);
else ++itr;
}
}
void OperationsThread::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(Operations::iterator itr = _operations.begin();
itr!=_operations.end();)
{
if ((*itr)->getName()==name) itr = _operations.erase(itr);
else ++itr;
}
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationsThread::removeAllOperations()
{
osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_operations.clear();
if (_operations.empty())
{
_operationsBlock->set(false);
}
}
void OperationsThread::run()
{
// make the graphics context current.
GraphicsContext* graphicsContext = dynamic_cast<GraphicsContext*>(_parent.get());
if (graphicsContext)
{
graphicsContext->makeCurrent();
}
osg::notify(osg::INFO)<<"Doing run "<<this<<" isRunning()="<<isRunning()<<std::endl;
bool firstTime = true;
Operations::iterator itr = _operations.begin();
do
{
// osg::notify(osg::NOTICE)<<"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
{
if (itr == _operations.end()) itr = _operations.begin();
}
// osg::notify(osg::INFO)<<"get op "<<_done<<" "<<this<<std::endl;
// get the front of the file request list.
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
if (!_operations.empty())
{
// get the next item
_currentOperation = *itr;
if (!_currentOperation->getKeep())
{
// osg::notify(osg::INFO)<<"removing "<<_currentOperation->getName()<<std::endl;
// remove it from the opeations queue
itr = _operations.erase(itr);
// osg::notify(osg::INFO)<<"size "<<_operations.size()<<std::endl;
if (_operations.empty())
{
// osg::notify(osg::INFO)<<"setting block "<<_operations.size()<<std::endl;
_operationsBlock->set(false);
}
}
else
{
// osg::notify(osg::INFO)<<"increment "<<_currentOperation->getName()<<std::endl;
// move on to the next operation in the list.
++itr;
}
}
}
if (_currentOperation.valid())
{
// osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;
// call the graphics operation.
(*_currentOperation)(_parent.get());
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
_currentOperation = 0;
}
}
if (firstTime)
{
// do a yield to get round a peculiar thread hang when testCancel() is called
// in certain cirumstances - of which there is no particular pattern.
YieldCurrentThread();
firstTime = false;
}
// osg::notify(osg::NOTICE)<<"operations.size()="<<_operations.size()<<" done="<<_done<<" testCancel()"<<testCancel()<<std::endl;
} while (!testCancel() && !_done);
if (graphicsContext)
{
graphicsContext->releaseContext();
}
osg::notify(osg::INFO)<<"exit loop "<<this<<" isRunning()="<<isRunning()<<std::endl;
}

View File

@@ -890,9 +890,23 @@ void RenderStage::draw(osg::RenderInfo& renderInfo,RenderLeaf*& previous)
if (useThread)
{
#if 1
ref_ptr<osg::BlockAndFlushOperation> block = new osg::BlockAndFlushOperation;
useThread->add(new DrawInnerOperation( this, renderInfo ));
useThread->add(block.get());
// wait till the DrawInnerOperations is complete.
block->block();
doCopyTexture = false;
#else
useThread->add(new DrawInnerOperation( this, renderInfo ), true);
doCopyTexture = false;
#endif
}
else
{

View File

@@ -16,13 +16,13 @@
#include <osg/CopyOp>
#include <osg/DisplaySettings>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>
#include <osg/Image>
#include <osg/Matrix>
#include <osg/Matrixd>
#include <osg/Matrixf>
#include <osg/NodeVisitor>
#include <osg/Object>
#include <osg/OperationsThread>
#include <osg/State>
#include <osg/Stats>
#include <osg/Texture>

View File

@@ -12,8 +12,8 @@
#include <OpenThreads/Mutex>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>
#include <osg/Object>
#include <osg/OperationsThread>
#include <osg/State>
#include <osg/Vec4>

View File

@@ -44,172 +44,18 @@ BEGIN_OBJECT_REFLECTOR(osg::BarrierOperation)
I_PublicMemberProperty(osg::BarrierOperation::PreBlockOp, _preBlockOp);
END_REFLECTOR
BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::Operation)
BEGIN_OBJECT_REFLECTOR(osg::BlockAndFlushOperation)
I_DeclaringFile("osg/GraphicsThread");
I_VirtualBaseType(osg::Referenced);
I_Constructor2(IN, const std::string &, name, IN, bool, keep,
____Operation__C5_std_string_R1__bool,
I_BaseType(osg::Operation);
I_BaseType(OpenThreads::Block);
I_Constructor0(____BlockAndFlushOperation,
"",
"");
I_Method1(void, setName, IN, const std::string &, name,
Properties::NON_VIRTUAL,
__void__setName__C5_std_string_R1,
"Set the human readable name of the operation. ",
"");
I_Method0(const std::string &, getName,
Properties::NON_VIRTUAL,
__C5_std_string_R1__getName,
"Get the human readable name of the operation. ",
"");
I_Method1(void, setKeep, IN, bool, keep,
Properties::NON_VIRTUAL,
__void__setKeep__bool,
"Set whether the operation should be kept once its been applied. ",
"");
I_Method0(bool, getKeep,
Properties::NON_VIRTUAL,
__bool__getKeep,
"Get whether the operation should be kept once its been applied. ",
"");
I_Method0(void, release,
Properties::VIRTUAL,
__void__release,
"if this operation is a barrier then release it. ",
"");
I_SimpleProperty(bool, Keep,
__bool__getKeep,
__void__setKeep__bool);
I_SimpleProperty(const std::string &, Name,
__C5_std_string_R1__getName,
__void__setName__C5_std_string_R1);
END_REFLECTOR
BEGIN_OBJECT_REFLECTOR(osg::OperationQueue)
I_DeclaringFile("osg/GraphicsThread");
I_BaseType(osg::Referenced);
I_Constructor0(____OperationQueue,
"",
"");
I_Method0(osg::RefBlock *, getOperationsBlock,
Properties::NON_VIRTUAL,
__RefBlock_P1__getOperationsBlock,
"",
"");
I_Method0(const osg::RefBlock *, getOperationsBlock,
Properties::NON_VIRTUAL,
__C5_RefBlock_P1__getOperationsBlock,
"",
"");
I_Method1(void, add, IN, osg::Operation *, operation,
Properties::NON_VIRTUAL,
__void__add__Operation_P1,
"Add operation to end of OperationQueue, this will be executed by the operation thread once this operation gets to the head of the queue. ",
"");
I_Method1(void, remove, IN, osg::Operation *, operation,
Properties::NON_VIRTUAL,
__void__remove__Operation_P1,
"Remove operation from OperationQueue. ",
"");
I_Method1(void, remove, IN, const std::string &, name,
Properties::NON_VIRTUAL,
__void__remove__C5_std_string_R1,
"Remove named operation from OperationQueue. ",
"");
I_Method0(void, removeAllOperations,
Properties::NON_VIRTUAL,
__void__removeAllOperations,
"Remove all operations from OperationQueue. ",
"");
I_SimpleProperty(osg::RefBlock *, OperationsBlock,
__RefBlock_P1__getOperationsBlock,
0);
END_REFLECTOR
BEGIN_OBJECT_REFLECTOR(osg::OperationsThread)
I_DeclaringFile("osg/GraphicsThread");
I_BaseType(osg::Referenced);
I_BaseType(OpenThreads::Thread);
I_Constructor0(____OperationsThread,
"",
"");
I_Method1(void, setParent, IN, osg::Object *, parent,
Properties::NON_VIRTUAL,
__void__setParent__Object_P1,
"",
"");
I_Method0(osg::Object *, getParent,
Properties::NON_VIRTUAL,
__Object_P1__getParent,
"",
"");
I_Method0(const osg::Object *, getParent,
Properties::NON_VIRTUAL,
__C5_Object_P1__getParent,
"",
"");
I_MethodWithDefaults2(void, add, IN, osg::Operation *, operation, , IN, bool, waitForCompletion, false,
Properties::NON_VIRTUAL,
__void__add__Operation_P1__bool,
"Add operation to end of OperationQueue, this will be executed by the graphics thread once this operation gets to the head of the queue. ",
"");
I_Method1(void, remove, IN, osg::Operation *, operation,
Properties::NON_VIRTUAL,
__void__remove__Operation_P1,
"Remove operation from OperationQueue. ",
"");
I_Method1(void, remove, IN, const std::string &, name,
Properties::NON_VIRTUAL,
__void__remove__C5_std_string_R1,
"Remove named operation from OperationQueue. ",
"");
I_Method0(void, removeAllOperations,
Properties::NON_VIRTUAL,
__void__removeAllOperations,
"Remove all operations from OperationQueue. ",
"");
I_Method0(osg::ref_ptr< osg::Operation >, getCurrentOperation,
Properties::NON_VIRTUAL,
__osg_ref_ptrT1_Operation___getCurrentOperation,
"Get the operation currently being run. ",
"");
I_Method0(void, run,
Properties::VIRTUAL,
__void__run,
"Run does the graphics thread run loop. ",
"");
I_Method1(void, setDone, IN, bool, done,
Properties::NON_VIRTUAL,
__void__setDone__bool,
"",
"");
I_Method0(bool, getDone,
Properties::NON_VIRTUAL,
__bool__getDone,
"",
"");
I_Method0(int, cancel,
Properties::VIRTUAL,
__int__cancel,
"Cancel this graphics thread. ",
"");
I_SimpleProperty(osg::ref_ptr< osg::Operation >, CurrentOperation,
__osg_ref_ptrT1_Operation___getCurrentOperation,
0);
I_SimpleProperty(bool, Done,
__bool__getDone,
__void__setDone__bool);
I_SimpleProperty(osg::Object *, Parent,
__Object_P1__getParent,
__void__setParent__Object_P1);
END_REFLECTOR
BEGIN_OBJECT_REFLECTOR(osg::RefBlock)
I_DeclaringFile("osg/GraphicsThread");
I_VirtualBaseType(osg::Referenced);
I_BaseType(OpenThreads::Block);
I_Constructor0(____RefBlock,
"",
"");
END_REFLECTOR
BEGIN_OBJECT_REFLECTOR(osg::ReleaseContext_Block_MakeCurrentOperation)

View File

@@ -12,9 +12,9 @@
#include <osg/FrameStamp>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>
#include <osg/Group>
#include <osg/Node>
#include <osg/OperationsThread>
#include <osg/PagedLOD>
#include <osg/State>
#include <osgDB/DatabasePager>

View File

@@ -13,9 +13,9 @@
#include <osg/BoundingSphere>
#include <osg/CopyOp>
#include <osg/GraphicsContext>
#include <osg/GraphicsThread>
#include <osg/NodeVisitor>
#include <osg/Object>
#include <osg/OperationsThread>
#include <osg/TransferFunction>
#include <osgTerrain/Layer>
#include <osgTerrain/Locator>

View File

@@ -13,7 +13,7 @@
#include <osg/ArgumentParser>
#include <osg/Camera>
#include <osg/FrameStamp>
#include <osg/GraphicsThread>
#include <osg/OperationsThread>
#include <osg/Timer>
#include <osgGA/EventQueue>
#include <osgViewer/CompositeViewer>

View File

@@ -14,8 +14,8 @@
#include <osg/ArgumentParser>
#include <osg/Camera>
#include <osg/FrameStamp>
#include <osg/GraphicsThread>
#include <osg/Node>
#include <osg/OperationsThread>
#include <osg/Timer>
#include <osgViewer/GraphicsWindow>
#include <osgViewer/Viewer>