Added an osgDB::ReadWriteMutex to help manage the ability to have serialize
write to objects but allow multiple threads to read at once in a read only way.
This commit is contained in:
@@ -37,15 +37,70 @@ class OSGDB_EXPORT ReentrantMutex : public OpenThreads::Mutex
|
||||
|
||||
private:
|
||||
|
||||
ReentrantMutex(const ReentrantMutex &):OpenThreads::Mutex() {}
|
||||
ReentrantMutex(const ReentrantMutex&):OpenThreads::Mutex() {}
|
||||
|
||||
ReentrantMutex &operator=(const ReentrantMutex &) {return *(this);}
|
||||
ReentrantMutex& operator =(const ReentrantMutex&) { return *(this); }
|
||||
|
||||
OpenThreads::Thread* _threadHoldingMutex;
|
||||
unsigned int _lockCount;
|
||||
|
||||
};
|
||||
|
||||
class OSGDB_EXPORT ReadWriteMutex
|
||||
{
|
||||
public:
|
||||
|
||||
ReadWriteMutex();
|
||||
|
||||
virtual ~ReadWriteMutex();
|
||||
|
||||
virtual int readLock();
|
||||
|
||||
virtual int readUnlock();
|
||||
|
||||
virtual int writeLock();
|
||||
|
||||
virtual int writeUnlock();
|
||||
|
||||
protected:
|
||||
|
||||
ReadWriteMutex(const ReadWriteMutex&) {}
|
||||
ReadWriteMutex& operator = (const ReadWriteMutex&) { return *(this); }
|
||||
|
||||
#if 1
|
||||
ReentrantMutex _readWriteMutex;
|
||||
ReentrantMutex _readCountMutex;
|
||||
#else
|
||||
OpenThreads::Mutex _readWriteMutex;
|
||||
OpenThreads::Mutex _readCountMutex;
|
||||
#endif
|
||||
unsigned int _readCount;
|
||||
|
||||
};
|
||||
|
||||
class ScopedReadLock
|
||||
{
|
||||
public:
|
||||
|
||||
ScopedReadLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.readLock(); }
|
||||
~ScopedReadLock() { _mutex.readUnlock(); }
|
||||
|
||||
protected:
|
||||
ReadWriteMutex& _mutex;
|
||||
};
|
||||
|
||||
|
||||
class ScopedWriteLock
|
||||
{
|
||||
public:
|
||||
|
||||
ScopedWriteLock(ReadWriteMutex& mutex):_mutex(mutex) { _mutex.writeLock(); }
|
||||
~ScopedWriteLock() { _mutex.writeUnlock(); }
|
||||
|
||||
protected:
|
||||
ReadWriteMutex& _mutex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -171,8 +171,6 @@ namespace osgParticle
|
||||
//added- 1/17/06- bgandere@nps.edu
|
||||
//a var to keep from doing multiple updates
|
||||
int _frameNumber;
|
||||
|
||||
OpenThreads::Mutex _cullUpdatelMutex;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include <osg/Vec3>
|
||||
#include <osg/BoundingBox>
|
||||
|
||||
#include <osgDB/ReentrantMutex>
|
||||
|
||||
namespace osgParticle
|
||||
{
|
||||
|
||||
@@ -163,6 +165,8 @@ namespace osgParticle
|
||||
virtual void drawImplementation(osg::State& state) const;
|
||||
|
||||
virtual osg::BoundingBox computeBound() const;
|
||||
|
||||
osgDB::ReadWriteMutex& getReadWriteMutex() const { return _readWriteMutex; }
|
||||
|
||||
protected:
|
||||
|
||||
@@ -201,6 +205,8 @@ namespace osgParticle
|
||||
int _detail;
|
||||
mutable int _draw_count;
|
||||
|
||||
mutable osgDB::ReadWriteMutex _readWriteMutex;
|
||||
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
||||
@@ -91,8 +91,6 @@ namespace osgParticle
|
||||
//added 1/17/06- bgandere@nps.edu
|
||||
//a var to keep from doing multiple updates per frame
|
||||
int _frameNumber;
|
||||
|
||||
OpenThreads::Mutex _cullUpdatelMutex;
|
||||
};
|
||||
|
||||
// INLINE FUNCTIONS
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
*/
|
||||
|
||||
#include <osgDB/ReentrantMutex>
|
||||
#include <OpenThreads/ScopedLock>
|
||||
|
||||
#include <osg/Notify>
|
||||
|
||||
using namespace osgDB;
|
||||
using namespace OpenThreads;
|
||||
@@ -48,6 +50,7 @@ int ReentrantMutex::lock()
|
||||
|
||||
int ReentrantMutex::unlock()
|
||||
{
|
||||
#if 0
|
||||
if (_threadHoldingMutex==OpenThreads::Thread::CurrentThread() && _lockCount>0)
|
||||
{
|
||||
--_lockCount;
|
||||
@@ -57,6 +60,21 @@ int ReentrantMutex::unlock()
|
||||
return Mutex::unlock();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Error: ReentrantMutex::unlock() - unlocking from the wrong thread."<<std::endl;
|
||||
}
|
||||
#else
|
||||
if (_lockCount>0)
|
||||
{
|
||||
--_lockCount;
|
||||
if (_lockCount<=0)
|
||||
{
|
||||
_threadHoldingMutex = 0;
|
||||
return Mutex::unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -78,3 +96,49 @@ int ReentrantMutex::trylock()
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
ReadWriteMutex::ReadWriteMutex():
|
||||
_readCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
ReadWriteMutex::~ReadWriteMutex()
|
||||
{
|
||||
}
|
||||
|
||||
int ReadWriteMutex::readLock()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
|
||||
int result = 0;
|
||||
if (_readCount==0)
|
||||
{
|
||||
result = _readWriteMutex.lock();
|
||||
}
|
||||
++_readCount;
|
||||
return result;
|
||||
}
|
||||
|
||||
int ReadWriteMutex::readUnlock()
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_readCountMutex);
|
||||
int result = 0;
|
||||
if (_readCount>0)
|
||||
{
|
||||
--_readCount;
|
||||
if (_readCount==0)
|
||||
{
|
||||
result = _readWriteMutex.unlock();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int ReadWriteMutex::writeLock()
|
||||
{
|
||||
return _readWriteMutex.lock();
|
||||
}
|
||||
|
||||
int ReadWriteMutex::writeUnlock()
|
||||
{
|
||||
return _readWriteMutex.unlock();
|
||||
}
|
||||
|
||||
@@ -64,13 +64,14 @@ void osgParticle::ParticleProcessor::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (nv.getFrameStamp())
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_cullUpdatelMutex);
|
||||
osgDB::ScopedWriteLock lock(_ps->getReadWriteMutex());
|
||||
|
||||
//added- 1/17/06- bgandere@nps.edu
|
||||
//a check to make sure we havent updated yet this frame
|
||||
if(_frameNumber < nv.getFrameStamp()->getFrameNumber())
|
||||
{
|
||||
|
||||
|
||||
// retrieve the current time
|
||||
double t = nv.getFrameStamp()->getReferenceTime();
|
||||
|
||||
|
||||
@@ -91,6 +91,8 @@ void osgParticle::ParticleSystem::update(double dt)
|
||||
|
||||
void osgParticle::ParticleSystem::drawImplementation(osg::State& state) const
|
||||
{
|
||||
osgDB::ScopedReadLock lock(_readWriteMutex);
|
||||
|
||||
// update the frame count, so other objects can detect when
|
||||
// this particle system is culled
|
||||
_last_frame = state.getFrameStamp()->getFrameNumber();
|
||||
|
||||
@@ -27,32 +27,30 @@ void osgParticle::ParticleSystemUpdater::traverse(osg::NodeVisitor& nv)
|
||||
{
|
||||
if (nv.getFrameStamp())
|
||||
{
|
||||
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_cullUpdatelMutex);
|
||||
|
||||
//added 1/17/06- bgandere@nps.edu
|
||||
//ensures ParticleSystem will only be updated once per frame
|
||||
//regardless of the number of cameras viewing it
|
||||
if( _frameNumber < nv.getFrameStamp()->getFrameNumber())
|
||||
{
|
||||
_frameNumber = nv.getFrameStamp()->getFrameNumber();
|
||||
|
||||
double t = nv.getFrameStamp()->getReferenceTime();
|
||||
if (_t0 != -1)
|
||||
if (_t0 != -1.0)
|
||||
{
|
||||
ParticleSystem_Vector::iterator i;
|
||||
for (i=_psv.begin(); i!=_psv.end(); ++i)
|
||||
{
|
||||
if (!i->get()->isFrozen() && (i->get()->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !i->get()->getFreezeOnCull()))
|
||||
ParticleSystem* ps = i->get();
|
||||
|
||||
osgDB::ScopedWriteLock lock(ps->getReadWriteMutex());
|
||||
|
||||
if (!ps->isFrozen() && (ps->getLastFrameNumber() >= (nv.getFrameStamp()->getFrameNumber() - 1) || !ps->getFreezeOnCull()))
|
||||
{
|
||||
i->get()->update(t - _t0);
|
||||
ps->update(t - _t0);
|
||||
}
|
||||
}
|
||||
}
|
||||
_t0 = t;
|
||||
}
|
||||
|
||||
//added- 1/17/06- bgandere@nps.edu
|
||||
//set frame number to the current frame number
|
||||
_frameNumber = nv.getFrameStamp()->getFrameNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user