| /* Reference-counted smart pointer class | |
| Copyright (C) 2016-2023 Free Software Foundation, Inc. | |
| This file is part of GDB. | |
| This program is free software; you can redistribute it and/or modify | |
| it under the terms of the GNU General Public License as published by | |
| the Free Software Foundation; either version 3 of the License, or | |
| (at your option) any later version. | |
| This program is distributed in the hope that it will be useful, | |
| but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| GNU General Public License for more details. | |
| You should have received a copy of the GNU General Public License | |
| along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
| #ifndef COMMON_GDB_REF_PTR_H | |
| #define COMMON_GDB_REF_PTR_H | |
| #include <cstddef> | |
| namespace gdb | |
| { | |
| /* An instance of this class either holds a reference to a | |
| reference-counted object or is "NULL". Reference counting is | |
| handled externally by a policy class. If the object holds a | |
| reference, then when the object is destroyed, the reference is | |
| decref'd. | |
| Normally an instance is constructed using a pointer. This sort of | |
| initialization lets this class manage the lifetime of that | |
| reference. | |
| Assignment and copy construction will make a new reference as | |
| appropriate. Assignment from a plain pointer is disallowed to | |
| avoid confusion about whether this acquires a new reference; | |
| instead use the "reset" method -- which, like the pointer | |
| constructor, transfers ownership. | |
| The policy class must provide two static methods: | |
| void incref (T *); | |
| void decref (T *); | |
| */ | |
| template<typename T, typename Policy> | |
| class ref_ptr | |
| { | |
| public: | |
| /* Create a new NULL instance. */ | |
| ref_ptr () | |
| : m_obj (NULL) | |
| { | |
| } | |
| /* Create a new NULL instance. Note that this is not explicit. */ | |
| ref_ptr (const std::nullptr_t) | |
| : m_obj (NULL) | |
| { | |
| } | |
| /* Create a new instance. OBJ is a reference, management of which | |
| is now transferred to this class. */ | |
| explicit ref_ptr (T *obj) | |
| : m_obj (obj) | |
| { | |
| } | |
| /* Copy another instance. */ | |
| ref_ptr (const ref_ptr &other) | |
| : m_obj (other.m_obj) | |
| { | |
| if (m_obj != NULL) | |
| Policy::incref (m_obj); | |
| } | |
| /* Transfer ownership from OTHER. */ | |
| ref_ptr (ref_ptr &&other) noexcept | |
| : m_obj (other.m_obj) | |
| { | |
| other.m_obj = NULL; | |
| } | |
| /* Destroy this instance. */ | |
| ~ref_ptr () | |
| { | |
| if (m_obj != NULL) | |
| Policy::decref (m_obj); | |
| } | |
| /* Copy another instance. */ | |
| ref_ptr &operator= (const ref_ptr &other) | |
| { | |
| /* Do nothing on self-assignment. */ | |
| if (this != &other) | |
| { | |
| reset (other.m_obj); | |
| if (m_obj != NULL) | |
| Policy::incref (m_obj); | |
| } | |
| return *this; | |
| } | |
| /* Transfer ownership from OTHER. */ | |
| ref_ptr &operator= (ref_ptr &&other) | |
| { | |
| /* Do nothing on self-assignment. */ | |
| if (this != &other) | |
| { | |
| reset (other.m_obj); | |
| other.m_obj = NULL; | |
| } | |
| return *this; | |
| } | |
| /* Change this instance's referent. OBJ is a reference, management | |
| of which is now transferred to this class. */ | |
| void reset (T *obj) | |
| { | |
| if (m_obj != NULL) | |
| Policy::decref (m_obj); | |
| m_obj = obj; | |
| } | |
| /* Return this instance's referent without changing the state of | |
| this class. */ | |
| T *get () const | |
| { | |
| return m_obj; | |
| } | |
| /* Return this instance's referent, and stop managing this | |
| reference. The caller is now responsible for the ownership of | |
| the reference. */ | |
| ATTRIBUTE_UNUSED_RESULT T *release () | |
| { | |
| T *result = m_obj; | |
| m_obj = NULL; | |
| return result; | |
| } | |
| /* Let users refer to members of the underlying pointer. */ | |
| T *operator-> () const | |
| { | |
| return m_obj; | |
| } | |
| /* Acquire a new reference and return a ref_ptr that owns it. */ | |
| static ref_ptr<T, Policy> new_reference (T *obj) | |
| { | |
| Policy::incref (obj); | |
| return ref_ptr<T, Policy> (obj); | |
| } | |
| private: | |
| T *m_obj; | |
| }; | |
| template<typename T, typename Policy> | |
| inline bool operator== (const ref_ptr<T, Policy> &lhs, | |
| const ref_ptr<T, Policy> &rhs) | |
| { | |
| return lhs.get () == rhs.get (); | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator== (const ref_ptr<T, Policy> &lhs, const T *rhs) | |
| { | |
| return lhs.get () == rhs; | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator== (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) | |
| { | |
| return lhs.get () == nullptr; | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator== (const T *lhs, const ref_ptr<T, Policy> &rhs) | |
| { | |
| return lhs == rhs.get (); | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator== (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) | |
| { | |
| return nullptr == rhs.get (); | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator!= (const ref_ptr<T, Policy> &lhs, | |
| const ref_ptr<T, Policy> &rhs) | |
| { | |
| return lhs.get () != rhs.get (); | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator!= (const ref_ptr<T, Policy> &lhs, const T *rhs) | |
| { | |
| return lhs.get () != rhs; | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator!= (const ref_ptr<T, Policy> &lhs, const std::nullptr_t) | |
| { | |
| return lhs.get () != nullptr; | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator!= (const T *lhs, const ref_ptr<T, Policy> &rhs) | |
| { | |
| return lhs != rhs.get (); | |
| } | |
| template<typename T, typename Policy> | |
| inline bool operator!= (const std::nullptr_t, const ref_ptr<T, Policy> &rhs) | |
| { | |
| return nullptr != rhs.get (); | |
| } | |
| } | |
| #endif /* COMMON_GDB_REF_PTR_H */ |