123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- /* Reference-counted smart pointer class
- Copyright (C) 2016-2022 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 */
|