File: Referenced

package info (click to toggle)
openscenegraph 2.8.3-5
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 33,968 kB
  • ctags: 30,935
  • sloc: cpp: 287,169; ansic: 9,050; sh: 654; yacc: 548; objc: 374; makefile: 264; lex: 151; perl: 119
file content (194 lines) | stat: -rw-r--r-- 6,087 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* -*-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,
#include <osg/Export>

#include <OpenThreads/ScopedLock>
#include <OpenThreads/Mutex>

#include <OpenThreads/Atomic>
#if !defined(_OPENTHREADS_ATOMIC_USE_MUTEX)
# define _OSG_REFERENCED_USE_ATOMIC_OPERATIONS
#endif

namespace osg {

// forward declare, declared after Referenced below.
class DeleteHandler;
class Observer;

/** template class to help enforce static initialization order. */
template <typename T, T M()>
struct depends_on
{
    depends_on() { M(); }
};

/** 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 getGlobalReferencedMutex(); }
#else
        OpenThreads::Mutex* getRefMutex() const { return _refMutex; }
#endif

        /** Get the optional global Referenced mutex, this can be shared between all osg::Referenced.*/
        static OpenThreads::Mutex* getGlobalReferencedMutex();

        /** 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) const;

        /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/
        void removeObserver(Observer* observer) const;

    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;

        mutable OpenThreads::AtomicPtr _observerSetDataPtr;

        mutable OpenThreads::Atomic     _refCount;
#else
        
        mutable OpenThreads::Mutex*     _refMutex;

        mutable int                     _refCount;
        
        mutable 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;
    }
}

// intrusive_ptr_add_ref and intrusive_ptr_release allow
// use of osg Referenced classes with boost::intrusive_ptr
inline void intrusive_ptr_add_ref(Referenced* p) { p->ref(); }
inline void intrusive_ptr_release(Referenced* p) { p->unref(); }

}

#endif