summaryrefslogtreecommitdiff
path: root/gdbsupport/gdb_ref_ptr.h
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/gdb_ref_ptr.h')
-rw-r--r--gdbsupport/gdb_ref_ptr.h228
1 files changed, 228 insertions, 0 deletions
diff --git a/gdbsupport/gdb_ref_ptr.h b/gdbsupport/gdb_ref_ptr.h
new file mode 100644
index 00000000000..c5ef13f3dfa
--- /dev/null
+++ b/gdbsupport/gdb_ref_ptr.h
@@ -0,0 +1,228 @@
+/* Reference-counted smart pointer class
+
+ Copyright (C) 2016-2020 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)
+ : 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 */