xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/gdb_ref_ptr.h (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
17d62b00eSchristos /* Reference-counted smart pointer class
27d62b00eSchristos 
3*6881a400Schristos    Copyright (C) 2016-2023 Free Software Foundation, Inc.
47d62b00eSchristos 
57d62b00eSchristos    This file is part of GDB.
67d62b00eSchristos 
77d62b00eSchristos    This program is free software; you can redistribute it and/or modify
87d62b00eSchristos    it under the terms of the GNU General Public License as published by
97d62b00eSchristos    the Free Software Foundation; either version 3 of the License, or
107d62b00eSchristos    (at your option) any later version.
117d62b00eSchristos 
127d62b00eSchristos    This program is distributed in the hope that it will be useful,
137d62b00eSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
147d62b00eSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
157d62b00eSchristos    GNU General Public License for more details.
167d62b00eSchristos 
177d62b00eSchristos    You should have received a copy of the GNU General Public License
187d62b00eSchristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
197d62b00eSchristos 
207d62b00eSchristos #ifndef COMMON_GDB_REF_PTR_H
217d62b00eSchristos #define COMMON_GDB_REF_PTR_H
227d62b00eSchristos 
237d62b00eSchristos #include <cstddef>
247d62b00eSchristos 
257d62b00eSchristos namespace gdb
267d62b00eSchristos {
277d62b00eSchristos 
287d62b00eSchristos /* An instance of this class either holds a reference to a
297d62b00eSchristos    reference-counted object or is "NULL".  Reference counting is
307d62b00eSchristos    handled externally by a policy class.  If the object holds a
317d62b00eSchristos    reference, then when the object is destroyed, the reference is
327d62b00eSchristos    decref'd.
337d62b00eSchristos 
347d62b00eSchristos    Normally an instance is constructed using a pointer.  This sort of
357d62b00eSchristos    initialization lets this class manage the lifetime of that
367d62b00eSchristos    reference.
377d62b00eSchristos 
387d62b00eSchristos    Assignment and copy construction will make a new reference as
397d62b00eSchristos    appropriate.  Assignment from a plain pointer is disallowed to
407d62b00eSchristos    avoid confusion about whether this acquires a new reference;
417d62b00eSchristos    instead use the "reset" method -- which, like the pointer
427d62b00eSchristos    constructor, transfers ownership.
437d62b00eSchristos 
447d62b00eSchristos    The policy class must provide two static methods:
457d62b00eSchristos    void incref (T *);
467d62b00eSchristos    void decref (T *);
477d62b00eSchristos */
487d62b00eSchristos template<typename T, typename Policy>
497d62b00eSchristos class ref_ptr
507d62b00eSchristos {
517d62b00eSchristos  public:
527d62b00eSchristos 
537d62b00eSchristos   /* Create a new NULL instance.  */
547d62b00eSchristos   ref_ptr ()
557d62b00eSchristos     : m_obj (NULL)
567d62b00eSchristos   {
577d62b00eSchristos   }
587d62b00eSchristos 
597d62b00eSchristos   /* Create a new NULL instance.  Note that this is not explicit.  */
607d62b00eSchristos   ref_ptr (const std::nullptr_t)
617d62b00eSchristos     : m_obj (NULL)
627d62b00eSchristos   {
637d62b00eSchristos   }
647d62b00eSchristos 
657d62b00eSchristos   /* Create a new instance.  OBJ is a reference, management of which
667d62b00eSchristos      is now transferred to this class.  */
677d62b00eSchristos   explicit ref_ptr (T *obj)
687d62b00eSchristos     : m_obj (obj)
697d62b00eSchristos   {
707d62b00eSchristos   }
717d62b00eSchristos 
727d62b00eSchristos   /* Copy another instance.  */
737d62b00eSchristos   ref_ptr (const ref_ptr &other)
747d62b00eSchristos     : m_obj (other.m_obj)
757d62b00eSchristos   {
767d62b00eSchristos     if (m_obj != NULL)
777d62b00eSchristos       Policy::incref (m_obj);
787d62b00eSchristos   }
797d62b00eSchristos 
807d62b00eSchristos   /* Transfer ownership from OTHER.  */
817d62b00eSchristos   ref_ptr (ref_ptr &&other) noexcept
827d62b00eSchristos     : m_obj (other.m_obj)
837d62b00eSchristos   {
847d62b00eSchristos     other.m_obj = NULL;
857d62b00eSchristos   }
867d62b00eSchristos 
877d62b00eSchristos   /* Destroy this instance.  */
887d62b00eSchristos   ~ref_ptr ()
897d62b00eSchristos   {
907d62b00eSchristos     if (m_obj != NULL)
917d62b00eSchristos       Policy::decref (m_obj);
927d62b00eSchristos   }
937d62b00eSchristos 
947d62b00eSchristos   /* Copy another instance.  */
957d62b00eSchristos   ref_ptr &operator= (const ref_ptr &other)
967d62b00eSchristos   {
977d62b00eSchristos     /* Do nothing on self-assignment.  */
987d62b00eSchristos     if (this != &other)
997d62b00eSchristos       {
1007d62b00eSchristos 	reset (other.m_obj);
1017d62b00eSchristos 	if (m_obj != NULL)
1027d62b00eSchristos 	  Policy::incref (m_obj);
1037d62b00eSchristos       }
1047d62b00eSchristos     return *this;
1057d62b00eSchristos   }
1067d62b00eSchristos 
1077d62b00eSchristos   /* Transfer ownership from OTHER.  */
1087d62b00eSchristos   ref_ptr &operator= (ref_ptr &&other)
1097d62b00eSchristos   {
1107d62b00eSchristos     /* Do nothing on self-assignment.  */
1117d62b00eSchristos     if (this != &other)
1127d62b00eSchristos       {
1137d62b00eSchristos 	reset (other.m_obj);
1147d62b00eSchristos 	other.m_obj = NULL;
1157d62b00eSchristos       }
1167d62b00eSchristos     return *this;
1177d62b00eSchristos   }
1187d62b00eSchristos 
1197d62b00eSchristos   /* Change this instance's referent.  OBJ is a reference, management
1207d62b00eSchristos      of which is now transferred to this class.  */
1217d62b00eSchristos   void reset (T *obj)
1227d62b00eSchristos   {
1237d62b00eSchristos     if (m_obj != NULL)
1247d62b00eSchristos       Policy::decref (m_obj);
1257d62b00eSchristos     m_obj = obj;
1267d62b00eSchristos   }
1277d62b00eSchristos 
1287d62b00eSchristos   /* Return this instance's referent without changing the state of
1297d62b00eSchristos      this class.  */
1307d62b00eSchristos   T *get () const
1317d62b00eSchristos   {
1327d62b00eSchristos     return m_obj;
1337d62b00eSchristos   }
1347d62b00eSchristos 
1357d62b00eSchristos   /* Return this instance's referent, and stop managing this
1367d62b00eSchristos      reference.  The caller is now responsible for the ownership of
1377d62b00eSchristos      the reference.  */
1387d62b00eSchristos   ATTRIBUTE_UNUSED_RESULT T *release ()
1397d62b00eSchristos   {
1407d62b00eSchristos     T *result = m_obj;
1417d62b00eSchristos 
1427d62b00eSchristos     m_obj = NULL;
1437d62b00eSchristos     return result;
1447d62b00eSchristos   }
1457d62b00eSchristos 
1467d62b00eSchristos   /* Let users refer to members of the underlying pointer.  */
1477d62b00eSchristos   T *operator-> () const
1487d62b00eSchristos   {
1497d62b00eSchristos     return m_obj;
1507d62b00eSchristos   }
1517d62b00eSchristos 
1527d62b00eSchristos   /* Acquire a new reference and return a ref_ptr that owns it.  */
1537d62b00eSchristos   static ref_ptr<T, Policy> new_reference (T *obj)
1547d62b00eSchristos   {
1557d62b00eSchristos     Policy::incref (obj);
1567d62b00eSchristos     return ref_ptr<T, Policy> (obj);
1577d62b00eSchristos   }
1587d62b00eSchristos 
1597d62b00eSchristos  private:
1607d62b00eSchristos 
1617d62b00eSchristos   T *m_obj;
1627d62b00eSchristos };
1637d62b00eSchristos 
1647d62b00eSchristos template<typename T, typename Policy>
1657d62b00eSchristos inline bool operator== (const ref_ptr<T, Policy> &lhs,
1667d62b00eSchristos 			const ref_ptr<T, Policy> &rhs)
1677d62b00eSchristos {
1687d62b00eSchristos   return lhs.get () == rhs.get ();
1697d62b00eSchristos }
1707d62b00eSchristos 
1717d62b00eSchristos template<typename T, typename Policy>
1727d62b00eSchristos inline bool operator== (const ref_ptr<T, Policy> &lhs, const T *rhs)
1737d62b00eSchristos {
1747d62b00eSchristos   return lhs.get () == rhs;
1757d62b00eSchristos }
1767d62b00eSchristos 
1777d62b00eSchristos template<typename T, typename Policy>
1787d62b00eSchristos inline bool operator== (const ref_ptr<T, Policy> &lhs, const std::nullptr_t)
1797d62b00eSchristos {
1807d62b00eSchristos   return lhs.get () == nullptr;
1817d62b00eSchristos }
1827d62b00eSchristos 
1837d62b00eSchristos template<typename T, typename Policy>
1847d62b00eSchristos inline bool operator== (const T *lhs, const ref_ptr<T, Policy> &rhs)
1857d62b00eSchristos {
1867d62b00eSchristos   return lhs == rhs.get ();
1877d62b00eSchristos }
1887d62b00eSchristos 
1897d62b00eSchristos template<typename T, typename Policy>
1907d62b00eSchristos inline bool operator== (const std::nullptr_t, const ref_ptr<T, Policy> &rhs)
1917d62b00eSchristos {
1927d62b00eSchristos   return nullptr == rhs.get ();
1937d62b00eSchristos }
1947d62b00eSchristos 
1957d62b00eSchristos template<typename T, typename Policy>
1967d62b00eSchristos inline bool operator!= (const ref_ptr<T, Policy> &lhs,
1977d62b00eSchristos 			const ref_ptr<T, Policy> &rhs)
1987d62b00eSchristos {
1997d62b00eSchristos   return lhs.get () != rhs.get ();
2007d62b00eSchristos }
2017d62b00eSchristos 
2027d62b00eSchristos template<typename T, typename Policy>
2037d62b00eSchristos inline bool operator!= (const ref_ptr<T, Policy> &lhs, const T *rhs)
2047d62b00eSchristos {
2057d62b00eSchristos   return lhs.get () != rhs;
2067d62b00eSchristos }
2077d62b00eSchristos 
2087d62b00eSchristos template<typename T, typename Policy>
2097d62b00eSchristos inline bool operator!= (const ref_ptr<T, Policy> &lhs, const std::nullptr_t)
2107d62b00eSchristos {
2117d62b00eSchristos   return lhs.get () != nullptr;
2127d62b00eSchristos }
2137d62b00eSchristos 
2147d62b00eSchristos template<typename T, typename Policy>
2157d62b00eSchristos inline bool operator!= (const T *lhs, const ref_ptr<T, Policy> &rhs)
2167d62b00eSchristos {
2177d62b00eSchristos   return lhs != rhs.get ();
2187d62b00eSchristos }
2197d62b00eSchristos 
2207d62b00eSchristos template<typename T, typename Policy>
2217d62b00eSchristos inline bool operator!= (const std::nullptr_t, const ref_ptr<T, Policy> &rhs)
2227d62b00eSchristos {
2237d62b00eSchristos   return nullptr != rhs.get ();
2247d62b00eSchristos }
2257d62b00eSchristos 
2267d62b00eSchristos }
2277d62b00eSchristos 
2287d62b00eSchristos #endif /* COMMON_GDB_REF_PTR_H */
229