5a4ce5a387
implementation of the atomic increment and decrement into a implementation file. This way inlining and compiler optimization can no longer happen for these implementations, but it fixes compilation on win32 msvc targets. I expect that this is still faster than with with mutexes. Also the i386 gcc target gets atomic operations with this patch. By using an implementation file we can guarantee that we have the right compiler flags available."
222 lines
6.7 KiB
C++
222 lines
6.7 KiB
C++
/* -*-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_REFERENCED
|
|
#define OSG_REFERENCED 1
|
|
|
|
// When building OSG with Java need to derive from Noodle::CBridgable class,
|
|
// therefore so OSG_JAVA_BUILD must be defined. Also the thread-safe ref/unref test
|
|
// as built in for the NoodleGlue wrapping. NoodleGlue has a Garbage collector mechanism
|
|
// which is very similar to osg::DeletionManager. So these aspects of osg::Referenced
|
|
// have been removed
|
|
//#define OSG_JAVA_BUILD
|
|
|
|
#include <osg/Export>
|
|
|
|
#ifdef OSG_JAVA_BUILD
|
|
#include <NoodleGlue/Bridgable.h>
|
|
#else
|
|
#include <OpenThreads/ScopedLock>
|
|
#include <OpenThreads/Mutex>
|
|
#endif
|
|
|
|
#include <OpenThreads/Atomic>
|
|
#if !defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
|
|
# define _OSG_REFERENCED_USE_ATOMIC_OPERATIONS
|
|
#endif
|
|
|
|
namespace osg {
|
|
|
|
#ifndef OSG_JAVA_BUILD
|
|
// forward declare, declared after Referenced below.
|
|
class DeleteHandler;
|
|
class Observer;
|
|
|
|
/** Base class from providing referencing counted objects.*/
|
|
class OSG_EXPORT Referenced
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
Referenced();
|
|
|
|
explicit Referenced(bool threadSafeRefUnref);
|
|
|
|
Referenced(const Referenced&);
|
|
|
|
inline Referenced& operator = (const Referenced&) { return *this; }
|
|
|
|
/** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
|
|
virtual void setThreadSafeRefUnref(bool threadSafe);
|
|
|
|
/** 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; }
|
|
#endif
|
|
|
|
/** 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; }
|
|
#endif
|
|
|
|
/** Increment the reference count by one, indicating that
|
|
this object has another pointer which is referencing it.*/
|
|
inline 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.*/
|
|
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 responsible 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; }
|
|
|
|
/** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
|
|
void addObserver(Observer* observer);
|
|
|
|
/** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
|
|
void removeObserver(Observer* observer);
|
|
|
|
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
|
|
* will be delegated to.*/
|
|
static void setDeleteHandler(DeleteHandler* handler);
|
|
|
|
/** Get a DeleteHandler.*/
|
|
static DeleteHandler* getDeleteHandler();
|
|
|
|
|
|
protected:
|
|
|
|
virtual ~Referenced();
|
|
|
|
void deleteUsingDeleteHandler() const;
|
|
|
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
|
struct ObserverSetData;
|
|
|
|
OpenThreads::AtomicPtr _observerSetDataPtr;
|
|
|
|
mutable OpenThreads::Atomic _refCount;
|
|
#else
|
|
|
|
mutable OpenThreads::Mutex* _refMutex;
|
|
|
|
mutable int _refCount;
|
|
|
|
void* _observers;
|
|
#endif
|
|
};
|
|
|
|
inline void Referenced::ref() const
|
|
{
|
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
|
++_refCount;
|
|
#else
|
|
if (_refMutex)
|
|
{
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
|
++_refCount;
|
|
}
|
|
else
|
|
{
|
|
++_refCount;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
inline void Referenced::unref() const
|
|
{
|
|
#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
|
|
bool needDelete = (--_refCount == 0);
|
|
#else
|
|
bool needDelete = false;
|
|
if (_refMutex)
|
|
{
|
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
|
--_refCount;
|
|
needDelete = _refCount<=0;
|
|
}
|
|
else
|
|
{
|
|
--_refCount;
|
|
needDelete = _refCount<=0;
|
|
}
|
|
#endif
|
|
|
|
if (needDelete)
|
|
{
|
|
if (getDeleteHandler()) deleteUsingDeleteHandler();
|
|
else delete this;
|
|
}
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
/** Java wrappers use the CBridgable base-class for referencing
|
|
* and garbage collection.
|
|
*/
|
|
class OSG_EXPORT Referenced : public NoodleGlue::CBridgable
|
|
{
|
|
public:
|
|
/** Method not used in NoodleGlue referencing
|
|
*/
|
|
inline void unref_nodelete() const { --_refCount; }
|
|
inline int referenceCount() const { return _refCount; }
|
|
|
|
/* These methods are not used in JavaOSG */
|
|
void addObserver(Observer* observer) {}
|
|
void removeObserver(Observer* observer) {}
|
|
|
|
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() { return true; }
|
|
|
|
protected:
|
|
virtual ~Referenced() {}
|
|
};
|
|
#endif //OSG_JAVA_BUILD
|
|
|
|
}
|
|
|
|
#endif
|