root/OpenSceneGraph/trunk/src/osg/Referenced.cpp @ 9343

Revision 9343, 9.4 kB (checked in by robert, 6 years ago)

Where possible moved redundent C header includes from headers to source files

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[1529]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*/
[7186]13#include <stdlib.h>
14
[1414]15#include <osg/Referenced>
16#include <osg/Notify>
[4269]17#include <osg/ApplicationUsage>
[5014]18#include <osg/observer_ptr>
[2787]19
[1414]20#include <typeinfo>
[2787]21#include <memory>
[5014]22#include <set>
[1414]23
[3436]24#include <OpenThreads/ScopedLock>
25#include <OpenThreads/Mutex>
26
[6086]27#include <osg/DeleteHandler>
28
[1414]29namespace osg
30{
31
[7819]32//#define ENFORCE_THREADSAFE
33//#define DEBUG_OBJECT_ALLOCATION_DESTRUCTION
34
[7648]35// specialized smart pointer, used to get round auto_ptr<>'s lack of the destructor reseting itself to 0.
[5184]36struct DeleteHandlerPointer
37{
38    DeleteHandlerPointer():
39        _ptr(0) {}
40
41    DeleteHandlerPointer(DeleteHandler* ptr):
42        _ptr(ptr) {}
43
44    ~DeleteHandlerPointer()
45    {
46        delete _ptr;
47        _ptr = 0;
48    }
49
50    inline DeleteHandlerPointer& operator = (DeleteHandler* ptr)
51    {
52        if (_ptr==ptr) return *this;
53        delete _ptr;
54        _ptr = ptr;
55        return *this;
56    }
57
58    void reset(DeleteHandler* ptr)
59    {
60        if (_ptr==ptr) return;
61        delete _ptr;
62        _ptr = ptr;
63    }
64
65    inline DeleteHandler& operator*()  { return *_ptr; }
66
67    inline const DeleteHandler& operator*() const { return *_ptr; }
68
69    inline DeleteHandler* operator->() { return _ptr; }
70
71    inline const DeleteHandler* operator->() const   { return _ptr; }
72
73    DeleteHandler* get() { return _ptr; }
74
75    const DeleteHandler* get() const { return _ptr; }
76
77    DeleteHandler* _ptr;
78};
79
[9023]80OpenThreads::Mutex* Referenced::getGlobalReferencedMutex()
81{
[9047]82    static OpenThreads::Mutex s_ReferencedGlobalMutext;
83    return &s_ReferencedGlobalMutext;
[9023]84}
[5184]85
[5014]86typedef std::set<Observer*> ObserverSet;
87
[8519]88#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[8465]89struct Referenced::ObserverSetData {
90   OpenThreads::Mutex _mutex;
91   ObserverSet _observers;
92};
[8519]93#endif
[7261]94
[8465]95#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[3436]96static bool s_useThreadSafeReferenceCounting = getenv("OSG_THREAD_SAFE_REF_UNREF")!=0;
[8465]97#endif
[5184]98// static std::auto_ptr<DeleteHandler> s_deleteHandler(0);
99static DeleteHandlerPointer s_deleteHandler(0);
100
[4269]101static ApplicationUsageProxy Referenced_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREAD_SAFE_REF_UNREF","");
[3436]102
103void Referenced::setThreadSafeReferenceCounting(bool enableThreadSafeReferenceCounting)
104{
[8465]105#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[3436]106    s_useThreadSafeReferenceCounting = enableThreadSafeReferenceCounting;
[8465]107#endif
[3436]108}
109
110bool Referenced::getThreadSafeReferenceCounting()
111{
[8465]112#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
113    return true;
114#else
[3436]115    return s_useThreadSafeReferenceCounting;
[8465]116#endif
[3436]117}
118
119
[1414]120void Referenced::setDeleteHandler(DeleteHandler* handler)
121{
[3215]122    s_deleteHandler.reset(handler);
[1414]123}
124
125DeleteHandler* Referenced::getDeleteHandler()
126{
127    return s_deleteHandler.get();
128}
129
[7819]130#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
131OpenThreads::Mutex& getNumObjectMutex()
132{
133    static OpenThreads::Mutex s_numObjectMutex;
134    return s_numObjectMutex;
135}
136static int s_numObjects = 0;
137#endif
138
[5014]139Referenced::Referenced():
[8465]140#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
141    _observerSetDataPtr(0),
142    _refCount(0)
143#else
[5014]144    _refMutex(0),
145    _refCount(0),
146    _observers(0)
[8465]147#endif
[3855]148{
[8465]149#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[7261]150#ifndef ENFORCE_THREADSAFE
151    if (s_useThreadSafeReferenceCounting)
152#endif
153        _refMutex = new OpenThreads::Mutex;
[8465]154#endif
[7819]155       
156#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
157    {
158        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getNumObjectMutex());
159        ++s_numObjects;
160        osg::notify(osg::NOTICE)<<"Object created, total num="<<s_numObjects<<std::endl;
161    }
162#endif
163
[3855]164}
[3436]165
[5125]166Referenced::Referenced(bool threadSafeRefUnref):
[8465]167#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
168    _observerSetDataPtr(0),
169    _refCount(0)
170#else
[5125]171    _refMutex(0),
172    _refCount(0),
173    _observers(0)
[8465]174#endif
[5125]175{
[8465]176#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[7261]177#ifndef ENFORCE_THREADSAFE
178    if (threadSafeRefUnref)
179#endif
180        _refMutex = new OpenThreads::Mutex;
[8465]181#endif
[7819]182
183#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
184    {
185        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getNumObjectMutex());
186        ++s_numObjects;
187        osg::notify(osg::NOTICE)<<"Object created, total num="<<s_numObjects<<std::endl;
188    }
189#endif
[5125]190}
191
[5014]192Referenced::Referenced(const Referenced&):
[8465]193#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
194    _observerSetDataPtr(0),
195    _refCount(0)
196#else
[5014]197    _refMutex(0),
198    _refCount(0),
199    _observers(0)
[8465]200#endif
[3855]201{
[8465]202#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[7261]203#ifndef ENFORCE_THREADSAFE
204    if (s_useThreadSafeReferenceCounting)
205#endif
206        _refMutex = new OpenThreads::Mutex;
[8465]207#endif
[7819]208
209#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
210    {
211        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getNumObjectMutex());
212        ++s_numObjects;
213        osg::notify(osg::NOTICE)<<"Object created, total num="<<s_numObjects<<std::endl;
214    }
215#endif
[3855]216}
217
[1414]218Referenced::~Referenced()
219{
[7819]220#ifdef DEBUG_OBJECT_ALLOCATION_DESTRUCTION
221    {
222        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(getNumObjectMutex());
223        --s_numObjects;
224        osg::notify(osg::NOTICE)<<"Object deleted, total num="<<s_numObjects<<std::endl;
225    }
226#endif
227
[1414]228    if (_refCount>0)
229    {
230        notify(WARN)<<"Warning: deleting still referenced object "<<this<<" of type '"<<typeid(this).name()<<"'"<<std::endl;
231        notify(WARN)<<"         the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
232    }
[3855]233
[8465]234#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[5014]235    if (_observers)
236    {
237        ObserverSet* os = static_cast<ObserverSet*>(_observers);
238        for(ObserverSet::iterator itr = os->begin();
239            itr != os->end();
240            ++itr)
241        {
242            (*itr)->objectDeleted(this);
243        }
244        delete os;
245        _observers = 0;
246    }
247
[3855]248    if (_refMutex)
249    {
250        OpenThreads::Mutex* tmpMutexPtr = _refMutex;
251        _refMutex = 0;
252        delete tmpMutexPtr;
253    }
[8465]254#else
[8493]255    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get());
[8465]256    if (observerSetData)
257    {
258        for(ObserverSet::iterator itr = observerSetData->_observers.begin();
259            itr != observerSetData->_observers.end();
260            ++itr)
261        {
262            (*itr)->objectDeleted(this);
263        }
264        _observerSetDataPtr.assign(0, observerSetData);
265        delete observerSetData;
266    }
267#endif
[1414]268}
269
[3855]270void Referenced::setThreadSafeRefUnref(bool threadSafe)
271{
[8465]272#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[3855]273    if (threadSafe)
274    {
275        if (!_refMutex)
276        {
[7648]277            // we want thread safe ref()/unref() so assign a mutex
[3855]278            _refMutex = new OpenThreads::Mutex;
279        }
280    }
281    else
282    {
283        if (_refMutex)
284        {
285            // we don't want thread safe ref()/unref() so remove any assigned mutex
286            OpenThreads::Mutex* tmpMutexPtr = _refMutex;
287            _refMutex = 0;
288            delete tmpMutexPtr;
289        }
290    }
[8465]291#endif
[3855]292}
293
[3436]294
295void Referenced::unref_nodelete() const
296{
[8465]297#if !defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[3855]298    if (_refMutex)
[3436]299    {
[3855]300        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
[3436]301        --_refCount;
302    }
303    else
304    {
305        --_refCount;
306    }
[8465]307#else
308    --_refCount;
309#endif
[3436]310}
311
[5237]312void Referenced::addObserver(Observer* observer)
[5014]313{
[8465]314#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[8493]315    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get());
[8465]316    while (0 == observerSetData) {
317        ObserverSetData* newObserverSetData = new ObserverSetData;
318        if (!_observerSetDataPtr.assign(newObserverSetData, 0))
319            delete newObserverSetData;
[8493]320        observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get());
[8465]321    }
322    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(observerSetData->_mutex);
323    observerSetData->_observers.insert(observer);
324#else
[5014]325    if (_refMutex)
326    {
327        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
328
329        if (!_observers) _observers = new ObserverSet;
[5237]330        if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer);
[5014]331    }
332    else
333    {
334        if (!_observers) _observers = new ObserverSet;
[5237]335        if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer);
[5014]336    }
[8465]337#endif
[5014]338}
339
[5237]340void Referenced::removeObserver(Observer* observer)
[5014]341{
[8465]342#if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS)
[8493]343    ObserverSetData* observerSetData = static_cast<ObserverSetData*>(_observerSetDataPtr.get());
[8465]344    if (observerSetData)
345    {
346       OpenThreads::ScopedLock<OpenThreads::Mutex> lock(observerSetData->_mutex);
347       observerSetData->_observers.erase(observer);
348    }
349#else
[5014]350    if (_refMutex)
351    {
352        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
353
[5237]354        if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer);
[5014]355    }
356    else
357    {
[5237]358        if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer);
[5014]359    }
[8465]360#endif
[5014]361}
362
[7038]363void Referenced::deleteUsingDeleteHandler() const
[6086]364{
365    getDeleteHandler()->requestDelete(this);
366}
367
[6459]368} // end of namespace osg
Note: See TracBrowser for help on using the browser.