From Mathias Froehlich, added support for using OpenThreads::Atomic for thread safe ref/unref.
This commit is contained in:
parent
2ba5f002d2
commit
936edacc92
@ -30,6 +30,10 @@
|
|||||||
#include <OpenThreads/Mutex>
|
#include <OpenThreads/Mutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <OpenThreads/Atomic>
|
||||||
|
#if !defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
||||||
|
# define _OSG_REFERENCED_USE_ATOMIC_OPERATIONS
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace osg {
|
namespace osg {
|
||||||
|
|
||||||
@ -57,10 +61,19 @@ class OSG_EXPORT Referenced
|
|||||||
virtual void setThreadSafeRefUnref(bool threadSafe);
|
virtual void setThreadSafeRefUnref(bool threadSafe);
|
||||||
|
|
||||||
/** Get whether a mutex is used to ensure ref() and unref() are thread safe.*/
|
/** Get whether a mutex is used to ensure ref() and unref() are thread safe.*/
|
||||||
|
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
bool getThreadSafeRefUnref() const { return true; }
|
||||||
|
#else
|
||||||
bool getThreadSafeRefUnref() const { return _refMutex!=0; }
|
bool getThreadSafeRefUnref() const { return _refMutex!=0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Get the mutex used to ensure thread safety of ref()/unref(). */
|
/** Get the mutex used to ensure thread safety of ref()/unref(). */
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
OpenThreads::Mutex* getRefMutex() const { return 0; }
|
||||||
|
#else
|
||||||
OpenThreads::Mutex* getRefMutex() const { return _refMutex; }
|
OpenThreads::Mutex* getRefMutex() const { return _refMutex; }
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Increment the reference count by one, indicating that
|
/** Increment the reference count by one, indicating that
|
||||||
this object has another pointer which is referencing it.*/
|
this object has another pointer which is referencing it.*/
|
||||||
@ -112,17 +125,28 @@ class OSG_EXPORT Referenced
|
|||||||
virtual ~Referenced();
|
virtual ~Referenced();
|
||||||
|
|
||||||
void deleteUsingDeleteHandler() const;
|
void deleteUsingDeleteHandler() const;
|
||||||
|
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
struct ObserverSetData;
|
||||||
|
|
||||||
|
OpenThreads::AtomicPtr<ObserverSetData> _observerSetDataPtr;
|
||||||
|
|
||||||
|
mutable OpenThreads::Atomic _refCount;
|
||||||
|
#else
|
||||||
|
|
||||||
mutable OpenThreads::Mutex* _refMutex;
|
mutable OpenThreads::Mutex* _refMutex;
|
||||||
|
|
||||||
mutable int _refCount;
|
mutable int _refCount;
|
||||||
|
|
||||||
void* _observers;
|
void* _observers;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void Referenced::ref() const
|
inline void Referenced::ref() const
|
||||||
{
|
{
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
++_refCount;
|
||||||
|
#else
|
||||||
if (_refMutex)
|
if (_refMutex)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||||
@ -132,10 +156,14 @@ inline void Referenced::ref() const
|
|||||||
{
|
{
|
||||||
++_refCount;
|
++_refCount;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void Referenced::unref() const
|
inline void Referenced::unref() const
|
||||||
{
|
{
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
bool needDelete = (--_refCount == 0);
|
||||||
|
#else
|
||||||
bool needDelete = false;
|
bool needDelete = false;
|
||||||
if (_refMutex)
|
if (_refMutex)
|
||||||
{
|
{
|
||||||
@ -148,6 +176,7 @@ inline void Referenced::unref() const
|
|||||||
--_refCount;
|
--_refCount;
|
||||||
needDelete = _refCount<=0;
|
needDelete = _refCount<=0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (needDelete)
|
if (needDelete)
|
||||||
{
|
{
|
||||||
|
@ -82,8 +82,14 @@ struct DeleteHandlerPointer
|
|||||||
|
|
||||||
typedef std::set<Observer*> ObserverSet;
|
typedef std::set<Observer*> ObserverSet;
|
||||||
|
|
||||||
|
struct Referenced::ObserverSetData {
|
||||||
|
OpenThreads::Mutex _mutex;
|
||||||
|
ObserverSet _observers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
static bool s_useThreadSafeReferenceCounting = getenv("OSG_THREAD_SAFE_REF_UNREF")!=0;
|
static bool s_useThreadSafeReferenceCounting = getenv("OSG_THREAD_SAFE_REF_UNREF")!=0;
|
||||||
|
#endif
|
||||||
// static std::auto_ptr<DeleteHandler> s_deleteHandler(0);
|
// static std::auto_ptr<DeleteHandler> s_deleteHandler(0);
|
||||||
static DeleteHandlerPointer s_deleteHandler(0);
|
static DeleteHandlerPointer s_deleteHandler(0);
|
||||||
|
|
||||||
@ -91,12 +97,18 @@ static ApplicationUsageProxy Referenced_e0(ApplicationUsage::ENVIRONMENTAL_VARIA
|
|||||||
|
|
||||||
void Referenced::setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting)
|
void Referenced::setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting)
|
||||||
{
|
{
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
s_useThreadSafeReferenceCounting = enableThreadSafeReferenceCounting;
|
s_useThreadSafeReferenceCounting = enableThreadSafeReferenceCounting;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Referenced::getThreadSafeReferenceCounting()
|
bool Referenced::getThreadSafeReferenceCounting()
|
||||||
{
|
{
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
return s_useThreadSafeReferenceCounting;
|
return s_useThreadSafeReferenceCounting;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -120,14 +132,21 @@ static int s_numObjects = 0;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Referenced::Referenced():
|
Referenced::Referenced():
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
_observerSetDataPtr(0),
|
||||||
|
_refCount(0)
|
||||||
|
#else
|
||||||
_refMutex(0),
|
_refMutex(0),
|
||||||
_refCount(0),
|
_refCount(0),
|
||||||
_observers(0)
|
_observers(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
#ifndef ENFORCE_THREADSAFE
|
#ifndef ENFORCE_THREADSAFE
|
||||||
if (s_useThreadSafeReferenceCounting)
|
if (s_useThreadSafeReferenceCounting)
|
||||||
#endif
|
#endif
|
||||||
_refMutex = new OpenThreads::Mutex;
|
_refMutex = new OpenThreads::Mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
||||||
{
|
{
|
||||||
@ -140,16 +159,21 @@ Referenced::Referenced():
|
|||||||
}
|
}
|
||||||
|
|
||||||
Referenced::Referenced(bool threadSafeRefUnref):
|
Referenced::Referenced(bool threadSafeRefUnref):
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
_observerSetDataPtr(0),
|
||||||
|
_refCount(0)
|
||||||
|
#else
|
||||||
_refMutex(0),
|
_refMutex(0),
|
||||||
_refCount(0),
|
_refCount(0),
|
||||||
_observers(0)
|
_observers(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
// if (!threadSafeRefUnref) osg::notify(osg::NOTICE)<<"Not ThreadSaef "<<std::endl;
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
|
||||||
#ifndef ENFORCE_THREADSAFE
|
#ifndef ENFORCE_THREADSAFE
|
||||||
if (threadSafeRefUnref)
|
if (threadSafeRefUnref)
|
||||||
#endif
|
#endif
|
||||||
_refMutex = new OpenThreads::Mutex;
|
_refMutex = new OpenThreads::Mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
||||||
{
|
{
|
||||||
@ -161,14 +185,21 @@ Referenced::Referenced(bool threadSafeRefUnref):
|
|||||||
}
|
}
|
||||||
|
|
||||||
Referenced::Referenced(const Referenced&):
|
Referenced::Referenced(const Referenced&):
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
_observerSetDataPtr(0),
|
||||||
|
_refCount(0)
|
||||||
|
#else
|
||||||
_refMutex(0),
|
_refMutex(0),
|
||||||
_refCount(0),
|
_refCount(0),
|
||||||
_observers(0)
|
_observers(0)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
#ifndef ENFORCE_THREADSAFE
|
#ifndef ENFORCE_THREADSAFE
|
||||||
if (s_useThreadSafeReferenceCounting)
|
if (s_useThreadSafeReferenceCounting)
|
||||||
#endif
|
#endif
|
||||||
_refMutex = new OpenThreads::Mutex;
|
_refMutex = new OpenThreads::Mutex;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
|
||||||
{
|
{
|
||||||
@ -195,6 +226,7 @@ Referenced::~Referenced()
|
|||||||
notify(WARN)<<" the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
|
notify(WARN)<<" the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
if (_observers)
|
if (_observers)
|
||||||
{
|
{
|
||||||
ObserverSet* os = static_cast<ObserverSet*>(_observers);
|
ObserverSet* os = static_cast<ObserverSet*>(_observers);
|
||||||
@ -214,10 +246,25 @@ Referenced::~Referenced()
|
|||||||
_refMutex = 0;
|
_refMutex = 0;
|
||||||
delete tmpMutexPtr;
|
delete tmpMutexPtr;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
ObserverSetData* observerSetData = _observerSetDataPtr.get();
|
||||||
|
if (observerSetData)
|
||||||
|
{
|
||||||
|
for(ObserverSet::iterator itr = observerSetData->_observers.begin();
|
||||||
|
itr != observerSetData->_observers.end();
|
||||||
|
++itr)
|
||||||
|
{
|
||||||
|
(*itr)->objectDeleted(this);
|
||||||
|
}
|
||||||
|
_observerSetDataPtr.assign(0, observerSetData);
|
||||||
|
delete observerSetData;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Referenced::setThreadSafeRefUnref(bool threadSafe)
|
void Referenced::setThreadSafeRefUnref(bool threadSafe)
|
||||||
{
|
{
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
if (threadSafe)
|
if (threadSafe)
|
||||||
{
|
{
|
||||||
if (!_refMutex)
|
if (!_refMutex)
|
||||||
@ -236,11 +283,13 @@ void Referenced::setThreadSafeRefUnref(bool threadSafe)
|
|||||||
delete tmpMutexPtr;
|
delete tmpMutexPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Referenced::unref_nodelete() const
|
void Referenced::unref_nodelete() const
|
||||||
{
|
{
|
||||||
|
#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
if (_refMutex)
|
if (_refMutex)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||||
@ -250,10 +299,24 @@ void Referenced::unref_nodelete() const
|
|||||||
{
|
{
|
||||||
--_refCount;
|
--_refCount;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
--_refCount;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Referenced::addObserver(Observer* observer)
|
void Referenced::addObserver(Observer* observer)
|
||||||
{
|
{
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
ObserverSetData* observerSetData = _observerSetDataPtr.get();
|
||||||
|
while (0 == observerSetData) {
|
||||||
|
ObserverSetData* newObserverSetData = new ObserverSetData;
|
||||||
|
if (!_observerSetDataPtr.assign(newObserverSetData, 0))
|
||||||
|
delete newObserverSetData;
|
||||||
|
observerSetData = _observerSetDataPtr.get();
|
||||||
|
}
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(observerSetData->_mutex);
|
||||||
|
observerSetData->_observers.insert(observer);
|
||||||
|
#else
|
||||||
if (_refMutex)
|
if (_refMutex)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||||
@ -266,10 +329,19 @@ void Referenced::addObserver(Observer* observer)
|
|||||||
if (!_observers) _observers = new ObserverSet;
|
if (!_observers) _observers = new ObserverSet;
|
||||||
if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer);
|
if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Referenced::removeObserver(Observer* observer)
|
void Referenced::removeObserver(Observer* observer)
|
||||||
{
|
{
|
||||||
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
||||||
|
ObserverSetData* observerSetData = _observerSetDataPtr.get();
|
||||||
|
if (observerSetData)
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(observerSetData->_mutex);
|
||||||
|
observerSetData->_observers.erase(observer);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (_refMutex)
|
if (_refMutex)
|
||||||
{
|
{
|
||||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||||
@ -280,6 +352,7 @@ void Referenced::removeObserver(Observer* observer)
|
|||||||
{
|
{
|
||||||
if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer);
|
if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Referenced::deleteUsingDeleteHandler() const
|
void Referenced::deleteUsingDeleteHandler() const
|
||||||
|
Loading…
Reference in New Issue
Block a user