diff --git a/include/osg/Referenced b/include/osg/Referenced index daba13159..f1cf53284 100644 --- a/include/osg/Referenced +++ b/include/osg/Referenced @@ -17,12 +17,7 @@ #include -// #define THREAD_SAFE_REF_UNREF 1 - -#ifdef THREAD_SAFE_REF_UNREF - #include - #include -#endif +#include namespace osg { @@ -36,6 +31,8 @@ class SG_EXPORT Referenced { public: + + Referenced() { @@ -47,6 +44,38 @@ class SG_EXPORT Referenced inline Referenced& operator = (const Referenced&) { return *this; } + + + /** increment the reference count by one, indicating that + this object has another pointer which is referencing it.*/ + void ref() const; + + /** decrement the reference count by one, indicating that + a pointer to this object is referencing it. If the + reference count goes to zero, it is assumed that this object + is no longer referenced and is automatically deleted.*/ + void unref() const; + + /** decrement the reference count by one, indicating that + a pointer to this object is referencing it. However, do + not delete it, even if ref count goes to 0. Warning, unref_nodelete() + should only be called if the user knows exactly who will + be resonsible for, one should prefer unref() over unref_nodelete() + as the later can lead to memory leaks.*/ + void unref_nodelete() const; + + /** return the number pointers currently referencing this object. */ + inline int referenceCount() const { return _refCount; } + + + public: + + /** Set whether reference counting should be use a mutex to create thread reference counting.*/ + static void setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting); + + /** Get whether reference counting is active.*/ + static bool getThreadSafeReferenceCounting(); + friend class DeleteHandler; /** Set a DeleteHandler to which deletion of all referenced counted objects @@ -56,41 +85,12 @@ class SG_EXPORT Referenced /** Get a DeleteHandler.*/ static DeleteHandler* getDeleteHandler(); - - /** increment the reference count by one, indicating that - this object has another pointer which is referencing it.*/ - inline void ref() const - { -#ifdef THREAD_SAFE_REF_UNREF - OpenThreads::ScopedLock lock(_refMutex); -#endif - ++_refCount; - } - - /** decrement the reference count by one, indicating that - a pointer to this object is referencing it. If the - reference count goes to zero, it is assumed that this object - is no longer referenced and is automatically deleted.*/ - inline void unref() const; - - /** decrement the reference count by one, indicating that - a pointer to this object is referencing it. However, do - not delete it, even if ref count goes to 0. Warning, unref_nodelete() - should only be called if the user knows exactly who will - be resonsible for, one should prefer unref() over unref_nodelete() - as the later can lead to memory leaks.*/ - inline void unref_nodelete() const { --_refCount; } - - /** return the number pointers currently referencing this object. */ - inline int referenceCount() const { return _refCount; } - protected: virtual ~Referenced(); -#ifdef THREAD_SAFE_REF_UNREF mutable OpenThreads::Mutex _refMutex; -#endif + mutable int _refCount; }; @@ -121,22 +121,6 @@ class DeleteHandler virtual void requestDelete(const Referenced* object) { doDelete(object); } }; -inline void Referenced::unref() const -{ - bool needDelete = false; - { -#ifdef THREAD_SAFE_REF_UNREF - OpenThreads::ScopedLock lock(_refMutex); -#endif - --_refCount; - needDelete = _refCount<=0; - } - if (needDelete) - { - if (getDeleteHandler()) getDeleteHandler()->requestDelete(this); - else delete this; - } -} } diff --git a/src/osg/Referenced.cpp b/src/osg/Referenced.cpp index 00bc88267..973770b89 100644 --- a/src/osg/Referenced.cpp +++ b/src/osg/Referenced.cpp @@ -16,9 +16,27 @@ #include #include +#include +#include + + namespace osg { +static bool s_useThreadSafeReferenceCounting = getenv("OSG_THREAD_SAFE_REF_UNREF")!=0; + +void Referenced::setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting) +{ + s_useThreadSafeReferenceCounting = enableThreadSafeReferenceCounting; +} + +bool Referenced::getThreadSafeReferenceCounting() +{ + return s_useThreadSafeReferenceCounting; +} + + + static std::auto_ptr s_deleteHandler(0); void Referenced::setDeleteHandler(DeleteHandler* handler) @@ -31,6 +49,7 @@ DeleteHandler* Referenced::getDeleteHandler() return s_deleteHandler.get(); } + Referenced::~Referenced() { if (_refCount>0) @@ -40,4 +59,54 @@ Referenced::~Referenced() } } +void Referenced::ref() const +{ + if (s_useThreadSafeReferenceCounting) + { + OpenThreads::ScopedLock lock(_refMutex); + ++_refCount; + } + else + { + ++_refCount; + } + +} + +void Referenced::unref() const +{ + bool needDelete = false; + if (s_useThreadSafeReferenceCounting) + { + OpenThreads::ScopedLock lock(_refMutex); + --_refCount; + needDelete = _refCount<=0; + } + else + { + --_refCount; + needDelete = _refCount<=0; + } + + if (needDelete) + { + if (getDeleteHandler()) getDeleteHandler()->requestDelete(this); + else delete this; + } +} + +void Referenced::unref_nodelete() const +{ + if (s_useThreadSafeReferenceCounting) + { + OpenThreads::ScopedLock lock(_refMutex); + --_refCount; + } + else + { + --_refCount; + } +} + + }; // end of namespace osg