Commit | Line | Data |
---|---|---|
50315b21 TT |
1 | /* Reference-counted smart pointer class |
2 | ||
e2882c85 | 3 | Copyright (C) 2016-2018 Free Software Foundation, Inc. |
50315b21 TT |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #ifndef GDB_REF_PTR_H | |
21 | #define GDB_REF_PTR_H | |
22 | ||
23 | #include <cstddef> | |
24 | ||
25 | namespace gdb | |
26 | { | |
27 | ||
28 | /* An instance of this class either holds a reference to a | |
29 | reference-counted object or is "NULL". Reference counting is | |
30 | handled externally by a policy class. If the object holds a | |
31 | reference, then when the object is destroyed, the reference is | |
32 | decref'd. | |
33 | ||
34 | Normally an instance is constructed using a pointer. This sort of | |
35 | initialization lets this class manage the lifetime of that | |
36 | reference. | |
37 | ||
38 | Assignment and copy construction will make a new reference as | |
39 | appropriate. Assignment from a plain pointer is disallowed to | |
40 | avoid confusion about whether this acquires a new reference; | |
41 | instead use the "reset" method -- which, like the pointer | |
42 | constructor, transfers ownership. | |
43 | ||
44 | The policy class must provide two static methods: | |
45 | void incref (T *); | |
46 | void decref (T *); | |
47 | */ | |
48 | template<typename T, typename Policy> | |
49 | class ref_ptr | |
50 | { | |
51 | public: | |
52 | ||
53 | /* Create a new NULL instance. */ | |
54 | ref_ptr () | |
55 | : m_obj (NULL) | |
56 | { | |
57 | } | |
58 | ||
59 | /* Create a new NULL instance. Note that this is not explicit. */ | |
60 | ref_ptr (const std::nullptr_t) | |
61 | : m_obj (NULL) | |
62 | { | |
63 | } | |
64 | ||
65 | /* Create a new instance. OBJ is a reference, management of which | |
66 | is now transferred to this class. */ | |
67 | explicit ref_ptr (T *obj) | |
68 | : m_obj (obj) | |
69 | { | |
70 | } | |
71 | ||
72 | /* Copy another instance. */ | |
73 | ref_ptr (const ref_ptr &other) | |
74 | : m_obj (other.m_obj) | |
75 | { | |
76 | if (m_obj != NULL) | |
77 | Policy::incref (m_obj); | |
78 | } | |
79 | ||
80 | /* Transfer ownership from OTHER. */ | |
81 | ref_ptr (ref_ptr &&other) | |
82 | : m_obj (other.m_obj) | |
83 | { | |
84 | other.m_obj = NULL; | |
85 | } | |
86 | ||
87 | /* Destroy this instance. */ | |
88 | ~ref_ptr () | |
89 | { | |
90 | if (m_obj != NULL) | |
91 | Policy::decref (m_obj); | |
92 | } | |
93 | ||
94 | /* Copy another instance. */ | |
95 | ref_ptr &operator= (const ref_ptr &other) | |
96 | { | |
97 | /* Do nothing on self-assignment. */ | |
98 | if (this != &other) | |
99 | { | |
100 | reset (other.m_obj); | |
101 | if (m_obj != NULL) | |
102 | Policy::incref (m_obj); | |
103 | } | |
104 | return *this; | |
105 | } | |
106 | ||
107 | /* Transfer ownership from OTHER. */ | |
108 | ref_ptr &operator= (ref_ptr &&other) | |
109 | { | |
110 | /* Do nothing on self-assignment. */ | |
111 | if (this != &other) | |
112 | { | |
113 | reset (other.m_obj); | |
114 | other.m_obj = NULL; | |
115 | } | |
116 | return *this; | |
117 | } | |
118 | ||
119 | /* Change this instance's referent. OBJ is a reference, management | |
120 | of which is now transferred to this class. */ | |
121 | void reset (T *obj) | |
122 | { | |
123 | if (m_obj != NULL) | |
124 | Policy::decref (m_obj); | |
125 | m_obj = obj; | |
126 | } | |
127 | ||
128 | /* Return this instance's referent without changing the state of | |
129 | this class. */ | |
130 | T *get () const | |
131 | { | |
132 | return m_obj; | |
133 | } | |
134 | ||
135 | /* Return this instance's referent, and stop managing this | |
136 | reference. The caller is now responsible for the ownership of | |
137 | the reference. */ | |
138 | T *release () | |
139 | { | |
140 | T *result = m_obj; | |
141 | ||
142 | m_obj = NULL; | |
143 | return result; | |
144 | } | |
145 | ||
192b62ce TT |
146 | /* Let users refer to members of the underlying pointer. */ |
147 | T *operator-> () const | |
148 | { | |
149 | return m_obj; | |
150 | } | |
151 | ||
50315b21 TT |
152 | private: |
153 | ||
154 | T *m_obj; | |
155 | }; | |
156 | ||
157 | template<typename T, typename Policy> | |
158 | inline bool operator== (const ref_ptr<T, Policy> &lhs, | |
159 | const ref_ptr<T, Policy> &rhs) | |
160 | { | |
161 | return lhs.get () == rhs.get (); | |
162 | } | |
163 | ||
164 | template<typename T, typename Policy> | |
165 | inline bool operator== (const ref_ptr<T, Policy> &lhs, const T *rhs) | |
166 | { | |
167 | return lhs.get () == rhs; | |
168 | } | |
169 | ||
170 | template<typename T, typename Policy> | |
171 | inline bool operator== (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) | |
172 | { | |
173 | return lhs.get () == nullptr; | |
174 | } | |
175 | ||
176 | template<typename T, typename Policy> | |
177 | inline bool operator== (const T *lhs, const ref_ptr<T, Policy> &rhs) | |
178 | { | |
179 | return lhs == rhs.get (); | |
180 | } | |
181 | ||
182 | template<typename T, typename Policy> | |
183 | inline bool operator== (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) | |
184 | { | |
185 | return nullptr == rhs.get (); | |
186 | } | |
187 | ||
188 | template<typename T, typename Policy> | |
189 | inline bool operator!= (const ref_ptr<T, Policy> &lhs, | |
190 | const ref_ptr<T, Policy> &rhs) | |
191 | { | |
192 | return lhs.get () != rhs.get (); | |
193 | } | |
194 | ||
195 | template<typename T, typename Policy> | |
196 | inline bool operator!= (const ref_ptr<T, Policy> &lhs, const T *rhs) | |
197 | { | |
198 | return lhs.get () != rhs; | |
199 | } | |
200 | ||
201 | template<typename T, typename Policy> | |
202 | inline bool operator!= (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) | |
203 | { | |
204 | return lhs.get () != nullptr; | |
205 | } | |
206 | ||
207 | template<typename T, typename Policy> | |
208 | inline bool operator!= (const T *lhs, const ref_ptr<T, Policy> &rhs) | |
209 | { | |
210 | return lhs != rhs.get (); | |
211 | } | |
212 | ||
213 | template<typename T, typename Policy> | |
214 | inline bool operator!= (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) | |
215 | { | |
216 | return nullptr != rhs.get (); | |
217 | } | |
218 | ||
219 | } | |
220 | ||
221 | #endif /* GDB_REF_PTR_H */ |