/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_ |