/src/wxwidgets/include/wx/sharedptr.h
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | /////////////////////////////////////////////////////////////////////////////  | 
2  |  | // Name:        wx/sharedptr.h  | 
3  |  | // Purpose:     Shared pointer based on the counted_ptr<> template, which  | 
4  |  | //              is in the public domain  | 
5  |  | // Author:      Robert Roebling, Yonat Sharon  | 
6  |  | // Copyright:   Robert Roebling  | 
7  |  | // Licence:     wxWindows licence  | 
8  |  | /////////////////////////////////////////////////////////////////////////////  | 
9  |  |  | 
10  |  | #ifndef _WX_SHAREDPTR_H_  | 
11  |  | #define _WX_SHAREDPTR_H_  | 
12  |  |  | 
13  |  | #include "wx/defs.h"  | 
14  |  | #include "wx/atomic.h"  | 
15  |  |  | 
16  |  | // ----------------------------------------------------------------------------  | 
17  |  | // wxSharedPtr: A smart pointer with non-intrusive reference counting.  | 
18  |  | // ----------------------------------------------------------------------------  | 
19  |  |  | 
20  |  | template <class T>  | 
21  |  | class wxSharedPtr  | 
22  |  | { | 
23  |  | public:  | 
24  |  |     typedef T element_type;  | 
25  |  |  | 
26  |  |     explicit wxSharedPtr( T* ptr = nullptr )  | 
27  | 0  |         : m_ref(nullptr)  | 
28  | 0  |     { | 
29  | 0  |         if (ptr)  | 
30  | 0  |             m_ref = new reftype(ptr);  | 
31  | 0  |     }  | 
32  |  |  | 
33  |  |     template<typename Deleter>  | 
34  |  |     explicit wxSharedPtr(T* ptr, Deleter d)  | 
35  |  |         : m_ref(nullptr)  | 
36  |  |     { | 
37  |  |         if (ptr)  | 
38  |  |             m_ref = new reftype_with_deleter<Deleter>(ptr, d);  | 
39  |  |     }  | 
40  |  |  | 
41  | 0  |     ~wxSharedPtr()                           { Release(); } | 
42  | 0  |     wxSharedPtr(const wxSharedPtr& tocopy)   { Acquire(tocopy.m_ref); } | 
43  |  |  | 
44  |  |     wxSharedPtr& operator=( const wxSharedPtr& tocopy )  | 
45  |  |     { | 
46  |  |         if (this != &tocopy)  | 
47  |  |         { | 
48  |  |             Release();  | 
49  |  |             Acquire(tocopy.m_ref);  | 
50  |  |         }  | 
51  |  |         return *this;  | 
52  |  |     }  | 
53  |  |  | 
54  |  |     wxSharedPtr& operator=( T* ptr )  | 
55  | 0  |     { | 
56  | 0  |         if (get() != ptr)  | 
57  | 0  |         { | 
58  | 0  |             Release();  | 
59  | 0  |             if (ptr)  | 
60  | 0  |                 m_ref = new reftype(ptr);  | 
61  | 0  |         }  | 
62  | 0  |         return *this;  | 
63  | 0  |     }  | 
64  |  |  | 
65  |  |     // test for pointer validity: defining conversion to unspecified_bool_type  | 
66  |  |     // and not more obvious bool to avoid implicit conversions to integer types  | 
67  |  |     typedef T *(wxSharedPtr<T>::*unspecified_bool_type)() const;  | 
68  |  |     operator unspecified_bool_type() const  | 
69  | 0  |     { | 
70  | 0  |         if (m_ref && m_ref->m_ptr)  | 
71  | 0  |            return  &wxSharedPtr<T>::get;  | 
72  | 0  |         else  | 
73  | 0  |            return nullptr;  | 
74  | 0  |     }  | 
75  |  |  | 
76  |  |     T& operator*() const  | 
77  | 0  |     { | 
78  | 0  |         wxASSERT(m_ref != nullptr);  | 
79  | 0  |         wxASSERT(m_ref->m_ptr != nullptr);  | 
80  | 0  |         return *(m_ref->m_ptr);  | 
81  | 0  |     }  | 
82  |  |  | 
83  |  |     T* operator->() const  | 
84  | 0  |     { | 
85  | 0  |         wxASSERT(m_ref != nullptr);  | 
86  | 0  |         wxASSERT(m_ref->m_ptr != nullptr);  | 
87  | 0  |         return m_ref->m_ptr;  | 
88  | 0  |     }  | 
89  |  |  | 
90  |  |     T* get() const  | 
91  | 0  |     { | 
92  | 0  |         return m_ref ? m_ref->m_ptr : nullptr;  | 
93  | 0  |     }  | 
94  |  |  | 
95  |  |     void reset( T* ptr = nullptr )  | 
96  |  |     { | 
97  |  |         Release();  | 
98  |  |         if (ptr)  | 
99  |  |             m_ref = new reftype(ptr);  | 
100  |  |     }  | 
101  |  |  | 
102  |  |     template<typename Deleter>  | 
103  |  |     void reset(T* ptr, Deleter d)  | 
104  |  |     { | 
105  |  |         Release();  | 
106  |  |         if (ptr)  | 
107  |  |             m_ref = new reftype_with_deleter<Deleter>(ptr, d);  | 
108  |  |     }  | 
109  |  |  | 
110  |  |     bool unique()   const    { return (m_ref ? m_ref->m_count == 1 : true); } | 
111  |  |     long use_count() const   { return (m_ref ? (long)m_ref->m_count : 0); } | 
112  |  |  | 
113  |  |     template <class U>  | 
114  |  |     friend bool operator == (wxSharedPtr<T> const &a, wxSharedPtr<U> const &b )  | 
115  |  |     { | 
116  |  |         return a.get() == b.get();  | 
117  |  |     }  | 
118  |  |  | 
119  |  |     template <class U>  | 
120  |  |     friend bool operator != (wxSharedPtr<T> const &a, wxSharedPtr<U> const &b )  | 
121  |  |     { | 
122  |  |         return a.get() != b.get();  | 
123  |  |     }  | 
124  |  |  | 
125  |  | private:  | 
126  |  |  | 
127  |  |     struct reftype  | 
128  |  |     { | 
129  | 0  |         reftype(T* ptr) : m_ptr(ptr), m_count(1) {} | 
130  | 0  |         virtual ~reftype() = default;  | 
131  | 0  |         virtual void delete_ptr() { delete m_ptr; } | 
132  |  |  | 
133  |  |         T*          m_ptr;  | 
134  |  |         wxAtomicInt m_count;  | 
135  |  |     };  | 
136  |  |  | 
137  |  |     template<typename Deleter>  | 
138  |  |     struct reftype_with_deleter : public reftype  | 
139  |  |     { | 
140  |  |         reftype_with_deleter(T* ptr, Deleter d) : reftype(ptr), m_deleter(d) {} | 
141  |  |         virtual void delete_ptr() override { m_deleter(this->m_ptr); } | 
142  |  |  | 
143  |  |         Deleter m_deleter;  | 
144  |  |     };  | 
145  |  |  | 
146  |  |     reftype* m_ref;  | 
147  |  |  | 
148  |  |     void Acquire(reftype* ref)  | 
149  | 0  |     { | 
150  | 0  |         m_ref = ref;  | 
151  | 0  |         if (ref)  | 
152  | 0  |             wxAtomicInc( ref->m_count );  | 
153  | 0  |     }  | 
154  |  |  | 
155  |  |     void Release()  | 
156  | 0  |     { | 
157  | 0  |         if (m_ref)  | 
158  | 0  |         { | 
159  | 0  |             if (!wxAtomicDec( m_ref->m_count ))  | 
160  | 0  |             { | 
161  | 0  |                 m_ref->delete_ptr();  | 
162  | 0  |                 delete m_ref;  | 
163  | 0  |             }  | 
164  | 0  |             m_ref = nullptr;  | 
165  | 0  |         }  | 
166  | 0  |     }  | 
167  |  | };  | 
168  |  |  | 
169  |  | #endif // _WX_SHAREDPTR_H_  |