Added new methods into osg::Referenced for controlling the use of thread safe

ref/unref:

        /** 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();
This commit is contained in:
Robert Osfield 2004-09-27 14:15:13 +00:00
parent 7e5c87de6a
commit de0e616433
2 changed files with 105 additions and 52 deletions

View File

@ -17,12 +17,7 @@
#include <osg/Export>
// #define THREAD_SAFE_REF_UNREF 1
#ifdef THREAD_SAFE_REF_UNREF
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
#endif
#include <OpenThreads/Mutex>
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<OpenThreads::Mutex> 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<OpenThreads::Mutex> lock(_refMutex);
#endif
--_refCount;
needDelete = _refCount<=0;
}
if (needDelete)
{
if (getDeleteHandler()) getDeleteHandler()->requestDelete(this);
else delete this;
}
}
}

View File

@ -16,9 +16,27 @@
#include <typeinfo>
#include <memory>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>
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<DeleteHandler> 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<OpenThreads::Mutex> lock(_refMutex);
++_refCount;
}
else
{
++_refCount;
}
}
void Referenced::unref() const
{
bool needDelete = false;
if (s_useThreadSafeReferenceCounting)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> 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<OpenThreads::Mutex> lock(_refMutex);
--_refCount;
}
else
{
--_refCount;
}
}
}; // end of namespace osg