This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[RFA 1/8] Add gdb_ref_ptr.h
- From: Tom Tromey <tom at tromey dot com>
- To: gdb-patches at sourceware dot org
- Cc: Tom Tromey <tom at tromey dot com>
- Date: Mon, 28 Nov 2016 22:05:39 -0700
- Subject: [RFA 1/8] Add gdb_ref_ptr.h
- Authentication-results: sourceware.org; auth=none
- References: <1480395946-10924-1-git-send-email-tom@tromey.com>
This adds a new gdb_ref_ptr.h, that implements a reference-counting
smart pointer class, where the user of the class supplies a
reference-counting policy object.
This class will be used in the next patch, which changes most explicit
BFD reference counts to use this new type. Meanwhile, this patch
changes gdbpy_ref to be a specialization of this new class.
This change required adding new nullptr_t overloads some operators in
gdb_ref_ptr.h. I suspect this was needed because some Python header
redefines NULL, but I'm not certain.
2016-11-28 Tom Tromey <tom@tromey.com>
* common/gdb_ref_ptr.h: New file.
* python/py-ref.h (struct gdbpy_ref_policy): New.
(gdbpy_ref): Now a typedef.
---
gdb/ChangeLog | 6 ++
gdb/common/gdb_ref_ptr.h | 209 +++++++++++++++++++++++++++++++++++++++++++++++
gdb/python/py-ref.h | 135 ++----------------------------
3 files changed, 224 insertions(+), 126 deletions(-)
create mode 100644 gdb/common/gdb_ref_ptr.h
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 8cbe8ad..f455f7f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@
2016-11-28 Tom Tromey <tom@tromey.com>
+ * common/gdb_ref_ptr.h: New file.
+ * python/py-ref.h (struct gdbpy_ref_policy): New.
+ (gdbpy_ref): Now a typedef.
+
+2016-11-28 Tom Tromey <tom@tromey.com>
+
* utils.h (make_cleanup_htab_delete): Don't declare.
* utils.c (do_htab_delete_cleanup, make_cleanup_htab_delete):
Remove.
diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h
new file mode 100644
index 0000000..cc8ba94
--- /dev/null
+++ b/gdb/common/gdb_ref_ptr.h
@@ -0,0 +1,209 @@
+/* Reference-counted smart pointer class
+
+ Copyright (C) 2016 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 GDB_REF_PTR_H
+#define 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 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. */
+ T *release ()
+ {
+ T *result = m_obj;
+
+ m_obj = NULL;
+ return result;
+ }
+
+ private:
+
+ T *m_obj;
+};
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self,
+ const ref_ptr<T, POLICY> &other)
+{
+ return self.get () == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self, const T *other)
+{
+ return self.get () == other;
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const ref_ptr<T, POLICY> &self, const std::nullptr_t)
+{
+ return self.get () == nullptr;
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const T *self, const ref_ptr<T, POLICY> &other)
+{
+ return self == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator== (const std::nullptr_t, const ref_ptr<T, POLICY> &other)
+{
+ return nullptr == other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self,
+ const ref_ptr<T, POLICY> &other)
+{
+ return self.get () != other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self, const T *other)
+{
+ return self.get () != other;
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const ref_ptr<T, POLICY> &self, const std::nullptr_t)
+{
+ return self.get () != nullptr;
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const T *self, const ref_ptr<T, POLICY> &other)
+{
+ return self != other.get ();
+}
+
+template<typename T, typename POLICY>
+inline bool operator!= (const std::nullptr_t, const ref_ptr<T, POLICY> &other)
+{
+ return nullptr != other.get ();
+}
+
+}
+
+#endif /* GDB_REF_PTR_H */
diff --git a/gdb/python/py-ref.h b/gdb/python/py-ref.h
index f0e4aae..b2479bf 100644
--- a/gdb/python/py-ref.h
+++ b/gdb/python/py-ref.h
@@ -20,140 +20,23 @@
#ifndef GDB_PYTHON_REF_H
#define GDB_PYTHON_REF_H
-/* An instance of this class either holds a reference to a PyObject,
- or is "NULL". If it holds a reference, then when the object is
- destroyed, the PyObject is decref'd.
+#include "common/gdb_ref_ptr.h"
- Normally an instance is constructed using a PyObject*. 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 PyObject* is disallowed to
- avoid confusion about whether this acquires a new reference;
- instead use the "reset" method -- which, like the PyObject*
- constructor, transfers ownership.
-*/
-class gdbpy_ref
+/* A policy class for gdb::ref_ptr for Python reference counting. */
+struct gdbpy_ref_policy
{
- public:
-
- /* Create a new NULL instance. */
- gdbpy_ref ()
- : m_obj (NULL)
- {
- }
-
- /* Create a new instance. OBJ is a reference, management of which
- is now transferred to this class. */
- explicit gdbpy_ref (PyObject *obj)
- : m_obj (obj)
- {
- }
-
- /* Copy another instance. */
- gdbpy_ref (const gdbpy_ref &other)
- : m_obj (other.m_obj)
- {
- Py_XINCREF (m_obj);
- }
-
- /* Transfer ownership from OTHER. */
- gdbpy_ref (gdbpy_ref &&other)
- : m_obj (other.m_obj)
- {
- other.m_obj = NULL;
- }
-
- /* Destroy this instance. */
- ~gdbpy_ref ()
- {
- Py_XDECREF (m_obj);
- }
-
- /* Copy another instance. */
- gdbpy_ref &operator= (const gdbpy_ref &other)
- {
- /* Do nothing on self-assignment. */
- if (this != &other)
- {
- reset (other.m_obj);
- Py_XINCREF (m_obj);
- }
- return *this;
- }
-
- /* Transfer ownership from OTHER. */
- gdbpy_ref &operator= (gdbpy_ref &&other)
+ static void incref (PyObject *ptr)
{
- /* Do nothing on self-assignment. */
- if (this != &other)
- {
- reset (other.m_obj);
- other.m_obj = NULL;
- }
- return *this;
+ Py_INCREF (ptr);
}
- /* Change this instance's referent. OBJ is a reference, management
- of which is now transferred to this class. */
- void reset (PyObject *obj)
+ static void decref (PyObject *ptr)
{
- Py_XDECREF (m_obj);
- m_obj = obj;
+ Py_DECREF (ptr);
}
-
- /* Return this instance's referent. In Python terms this is a
- borrowed pointer. */
- PyObject *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. */
- PyObject *release ()
- {
- PyObject *result = m_obj;
-
- m_obj = NULL;
- return result;
- }
-
- private:
-
- PyObject *m_obj;
};
-inline bool operator== (const gdbpy_ref &self, const gdbpy_ref &other)
-{
- return self.get () == other.get ();
-}
-
-inline bool operator== (const gdbpy_ref &self, const PyObject *other)
-{
- return self.get () == other;
-}
-
-inline bool operator== (const PyObject *self, const gdbpy_ref &other)
-{
- return self == other.get ();
-}
-
-inline bool operator!= (const gdbpy_ref &self, const gdbpy_ref &other)
-{
- return self.get () != other.get ();
-}
-
-inline bool operator!= (const gdbpy_ref &self, const PyObject *other)
-{
- return self.get () != other;
-}
-
-inline bool operator!= (const PyObject *self, const gdbpy_ref &other)
-{
- return self != other.get ();
-}
+/* A gdb::ref_ptr that has been specialized for Python objects. */
+typedef gdb::ref_ptr<PyObject, gdbpy_ref_policy> gdbpy_ref;
#endif /* GDB_PYTHON_REF_H */
--
2.7.4