Branch data Line data Source code
1 : : /* -*-c++-*-
2 : : *
3 : : * Copyright (C) 2005-2006 Mathias Froehlich
4 : : *
5 : : * This program is free software; you can redistribute it and/or
6 : : * modify it under the terms of the GNU Lesser General Public License as
7 : : * published by the Free Software Foundation; either version 2 of the
8 : : * License, or (at your option) any later version.
9 : : *
10 : : * This program is distributed in the hope that it will be useful, but
11 : : * WITHOUT ANY WARRANTY; without even the implied warranty of
12 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : : * Lesser General Public License for more details.
14 : : *
15 : : * You should have received a copy of the GNU Lesser General Public License
16 : : * along with this program; if not, write to the Free Software
17 : : * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 : : *
19 : : */
20 : :
21 : : #ifndef SGSharedPtr_HXX
22 : : #define SGSharedPtr_HXX
23 : :
24 : : #include "SGReferenced.hxx"
25 : :
26 : : /// This class is a pointer proxy doing reference counting on the object
27 : : /// it is pointing to.
28 : : /// The SGSharedPtr class handles reference counting and possible
29 : : /// destruction if no nore references are in use automatically.
30 : : /// Classes derived from @SGReferenced can be handled with SGSharedPtr.
31 : : /// Once you have a SGSharedPtr available you can use it just like
32 : : /// a usual pointer with the exception that you don't need to delete it.
33 : : /// Such a reference is initialized by zero if not initialized with a
34 : : /// class pointer.
35 : : /// One thing you need to avoid are cyclic loops with such pointers.
36 : : /// As long as such a cyclic loop exists the reference count never drops
37 : : /// to zero and consequently the objects will never be destroyed.
38 : : /// Always try to use directed graphs where the references away from the
39 : : /// top node are made with SGSharedPtr's and the back references are done with
40 : : /// ordinary pointers.
41 : : /// There is a very good description of OpenSceneGraphs ref_ptr which is
42 : : /// pretty much the same than this one at
43 : : /// http://dburns.dhs.org/OSG/Articles/RefPointers/RefPointers.html
44 : :
45 : : template<typename T>
46 : : class SGSharedPtr {
47 : : public:
48 : 701 : SGSharedPtr(void) : _ptr(0)
49 : : {}
50 : 1303 : SGSharedPtr(T* ptr) : _ptr(ptr)
51 : 1303 : { get(_ptr); }
52 : 86293 : SGSharedPtr(const SGSharedPtr& p) : _ptr(p.ptr())
53 : 86293 : { get(_ptr); }
54 : : template<typename U>
55 : : SGSharedPtr(const SGSharedPtr<U>& p) : _ptr(p.ptr())
56 : : { get(_ptr); }
57 : 86293 : ~SGSharedPtr(void)
58 : 86293 : { put(); }
59 : :
60 : : SGSharedPtr& operator=(const SGSharedPtr& p)
61 : 0 : { assign(p.ptr()); return *this; }
62 : : template<typename U>
63 : : SGSharedPtr& operator=(const SGSharedPtr<U>& p)
64 : : { assign(p.ptr()); return *this; }
65 : : template<typename U>
66 : : SGSharedPtr& operator=(U* p)
67 : 2004 : { assign(p); return *this; }
68 : :
69 : : T* operator->(void) const
70 : 0 : { return _ptr; }
71 : : T& operator*(void) const
72 : : { return *_ptr; }
73 : : operator T*(void) const
74 : 65210 : { return _ptr; }
75 : : T* ptr(void) const
76 : 86293 : { return _ptr; }
77 : :
78 : : bool isShared(void) const
79 : : { return SGReferenced::shared(_ptr); }
80 : : unsigned getNumRefs(void) const
81 : : { return SGReferenced::count(_ptr); }
82 : :
83 : : bool valid(void) const
84 : : { return _ptr; }
85 : :
86 : : private:
87 : 2004 : void assign(T* p)
88 : 2004 : { get(p); put(); _ptr = p; }
89 : :
90 : : void get(const T* p) const
91 [ + - ][ # # ]: 89600 : { SGReferenced::get(p); }
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
[ # # ][ # # ]
[ + - ][ + - ]
[ # # ][ + - ]
[ - + ][ # # ]
92 : : void put(void)
93 [ + - ][ - + ]: 176594 : { if (!SGReferenced::put(_ptr)) { delete _ptr; _ptr = 0; } }
[ # # ][ - + ]
[ - + ][ # # ]
94 : :
95 : : // The reference itself.
96 : : T* _ptr;
97 : : };
98 : :
99 : : #endif
|