root/OpenSceneGraph/trunk/include/osg/Referenced @ 9862

Revision 9862, 5.8 kB (checked in by robert, 5 years ago)

Fixed indentation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#ifndef OSG_REFERENCED
15#define OSG_REFERENCED 1
16
17// When building OSG with Java need to derive from Noodle::CBridgable class,
18#include <osg/Export>
19
20#include <OpenThreads/ScopedLock>
21#include <OpenThreads/Mutex>
22
23#include <OpenThreads/Atomic>
24#if !defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
25# define _OSG_REFERENCED_USE_ATOMIC_OPERATIONS
26#endif
27
28namespace osg {
29
30// forward declare, declared after Referenced below.
31class DeleteHandler;
32class Observer;
33
34/** Base class from providing referencing counted objects.*/
35class OSG_EXPORT Referenced
36{
37
38    public:
39
40
41        Referenced();
42       
43        explicit Referenced(bool threadSafeRefUnref);
44
45        Referenced(const Referenced&);
46
47        inline Referenced& operator = (const Referenced&) { return *this; }
48
49        /** Set whether to use a mutex to ensure ref() and unref() are thread safe.*/
50        virtual void setThreadSafeRefUnref(bool threadSafe);
51
52        /** Get whether a mutex is used to ensure ref() and unref() are thread safe.*/
53
54#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
55        bool getThreadSafeRefUnref() const { return true; }
56#else
57        bool getThreadSafeRefUnref() const { return _refMutex!=0; }
58#endif
59
60        /** Get the mutex used to ensure thread safety of ref()/unref(). */
61#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
62        OpenThreads::Mutex* getRefMutex() const { return getGlobalReferencedMutex(); }
63#else
64        OpenThreads::Mutex* getRefMutex() const { return _refMutex; }
65#endif
66
67        /** Get the optional global Referenced mutex, this can be shared between all osg::Referenced.*/
68        static OpenThreads::Mutex* getGlobalReferencedMutex();
69
70        /** Increment the reference count by one, indicating that
71            this object has another pointer which is referencing it.*/
72        inline void ref() const;
73       
74        /** Decrement the reference count by one, indicating that
75            a pointer to this object is referencing it.  If the
76            reference count goes to zero, it is assumed that this object
77            is no longer referenced and is automatically deleted.*/
78        inline void unref() const;
79       
80        /** Decrement the reference count by one, indicating that
81            a pointer to this object is referencing it.  However, do
82            not delete it, even if ref count goes to 0.  Warning, unref_nodelete()
83            should only be called if the user knows exactly who will
84            be responsible for, one should prefer unref() over unref_nodelete()
85            as the later can lead to memory leaks.*/
86        void unref_nodelete() const;
87       
88        /** Return the number pointers currently referencing this object. */
89        inline int referenceCount() const { return _refCount; }
90
91        /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
92        void addObserver(Observer* observer) const;
93
94        /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
95        void removeObserver(Observer* observer) const;
96
97    public:
98
99        /** Set whether reference counting should be use a mutex to create thread reference counting.*/
100        static void setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting);
101       
102        /** Get whether reference counting is active.*/
103        static bool getThreadSafeReferenceCounting();
104
105        friend class DeleteHandler;
106
107        /** Set a DeleteHandler to which deletion of all referenced counted objects
108          * will be delegated to.*/
109        static void setDeleteHandler(DeleteHandler* handler);
110
111        /** Get a DeleteHandler.*/
112        static DeleteHandler* getDeleteHandler();
113
114       
115    protected:
116   
117        virtual ~Referenced();
118       
119        void deleteUsingDeleteHandler() const;
120
121#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
122        struct ObserverSetData;
123
124        mutable OpenThreads::AtomicPtr  _observerSetDataPtr;
125
126        mutable OpenThreads::Atomic     _refCount;
127#else
128       
129        mutable OpenThreads::Mutex*     _refMutex;
130
131        mutable int                     _refCount;
132       
133        mutable void*                   _observers;
134#endif
135};
136
137inline void Referenced::ref() const
138{
139#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
140    ++_refCount;
141#else
142    if (_refMutex)
143    {
144        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
145        ++_refCount;
146    }
147    else
148    {
149        ++_refCount;
150    }
151#endif
152}
153
154inline void Referenced::unref() const
155{
156#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
157    bool needDelete = (--_refCount == 0);
158#else
159    bool needDelete = false;
160    if (_refMutex)
161    {
162        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
163        --_refCount;
164        needDelete = _refCount<=0;
165    }
166    else
167    {
168        --_refCount;
169        needDelete = _refCount<=0;
170    }
171#endif
172
173    if (needDelete)
174    {
175        if (getDeleteHandler()) deleteUsingDeleteHandler();
176        else delete this;
177    }
178}
179
180// intrusive_ptr_add_ref and intrusive_ptr_release allow
181// use of osg Referenced classes with boost::intrusive_ptr
182inline void intrusive_ptr_add_ref(Referenced* p) { p->ref(); }
183inline void intrusive_ptr_release(Referenced* p) { p->unref(); }
184
185}
186
187#endif
Note: See TracBrowser for help on using the browser.