/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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 #ifdef OSG_JAVA_BUILD #include #else #include #include #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.*/ void setThreadSafeRefUnref(bool threadSafe); /** Get whether a mutex is used to ensure ref() and unref() are thread safe.*/ bool getThreadSafeRefUnref() const { return _refMutex!=0; } /** 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 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; } /** Add a Observer that is observering this object, notify the Observer when this object gets deleted.*/ void addObserver(Observer* observer); /** Add a Observer that is observering 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(); mutable OpenThreads::Mutex* _refMutex; mutable int _refCount; void* _observers; }; /** Class for override the default delete behavior so that users can implment their own object * deletion schemes. This might be done to help implement protection of multiple threads from deleting * objects unintentionally. * Note, the DeleteHandler cannot itself be reference counted, otherwise it * would be responsible for deleting itself! * An static auto_ptr<> is used internally in Referenced.cpp to manage the * DeleteHandler's memory.*/ class DeleteHandler { public: virtual ~DeleteHandler() {} /** flush any cache of objects that need to be deleted by doing an actual delete.*/ virtual void flush() {} inline void doDelete(const Referenced* object) { delete object; } /** Request the deletion of an object. * Depending on users implementation of DeleteHandler, the delete of the object may occur * straight away or be delayed until doDelete is called. * The default implementation does a delete straight away.*/ virtual void requestDelete(const Referenced* object) { doDelete(object); } }; inline void Referenced::ref() const { if (_refMutex) { OpenThreads::ScopedLock lock(*_refMutex); ++_refCount; } else { ++_refCount; } } inline void Referenced::unref() const { bool needDelete = false; if (_refMutex) { OpenThreads::ScopedLock lock(*_refMutex); --_refCount; needDelete = _refCount<=0; } else { --_refCount; needDelete = _refCount<=0; } if (needDelete) { if (getDeleteHandler()) getDeleteHandler()->requestDelete(this); 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