1 /* Reference-counted smart pointer class 2 3 Copyright (C) 2016-2020 Free Software Foundation, Inc. 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 COMMON_GDB_REF_PTR_H 21 #define COMMON_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) noexcept 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 ATTRIBUTE_UNUSED_RESULT T *release () 139 { 140 T *result = m_obj; 141 142 m_obj = NULL; 143 return result; 144 } 145 146 /* Let users refer to members of the underlying pointer. */ 147 T *operator-> () const 148 { 149 return m_obj; 150 } 151 152 /* Acquire a new reference and return a ref_ptr that owns it. */ 153 static ref_ptr<T, Policy> new_reference (T *obj) 154 { 155 Policy::incref (obj); 156 return ref_ptr<T, Policy> (obj); 157 } 158 159 private: 160 161 T *m_obj; 162 }; 163 164 template<typename T, typename Policy> 165 inline bool operator== (const ref_ptr<T, Policy> &lhs, 166 const ref_ptr<T, Policy> &rhs) 167 { 168 return lhs.get () == rhs.get (); 169 } 170 171 template<typename T, typename Policy> 172 inline bool operator== (const ref_ptr<T, Policy> &lhs, const T *rhs) 173 { 174 return lhs.get () == rhs; 175 } 176 177 template<typename T, typename Policy> 178 inline bool operator== (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) 179 { 180 return lhs.get () == nullptr; 181 } 182 183 template<typename T, typename Policy> 184 inline bool operator== (const T *lhs, const ref_ptr<T, Policy> &rhs) 185 { 186 return lhs == rhs.get (); 187 } 188 189 template<typename T, typename Policy> 190 inline bool operator== (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) 191 { 192 return nullptr == rhs.get (); 193 } 194 195 template<typename T, typename Policy> 196 inline bool operator!= (const ref_ptr<T, Policy> &lhs, 197 const ref_ptr<T, Policy> &rhs) 198 { 199 return lhs.get () != rhs.get (); 200 } 201 202 template<typename T, typename Policy> 203 inline bool operator!= (const ref_ptr<T, Policy> &lhs, const T *rhs) 204 { 205 return lhs.get () != rhs; 206 } 207 208 template<typename T, typename Policy> 209 inline bool operator!= (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) 210 { 211 return lhs.get () != nullptr; 212 } 213 214 template<typename T, typename Policy> 215 inline bool operator!= (const T *lhs, const ref_ptr<T, Policy> &rhs) 216 { 217 return lhs != rhs.get (); 218 } 219 220 template<typename T, typename Policy> 221 inline bool operator!= (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) 222 { 223 return nullptr != rhs.get (); 224 } 225 226 } 227 228 #endif /* COMMON_GDB_REF_PTR_H */ 229