public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Tom Tromey <tom@tromey.com>
To: gdb-patches@sourceware.org
Cc: Tom Tromey <tom@tromey.com>
Subject: [RFA 1/8] Add gdb_ref_ptr.h
Date: Tue, 29 Nov 2016 05:06:00 -0000	[thread overview]
Message-ID: <1480395946-10924-2-git-send-email-tom@tromey.com> (raw)
In-Reply-To: <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

  reply	other threads:[~2016-11-29  5:06 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-29  5:06 [RFA 0/8] C++-ification series #5 Tom Tromey
2016-11-29  5:06 ` Tom Tromey [this message]
2016-12-02 13:08   ` [RFA 1/8] Add gdb_ref_ptr.h Pedro Alves
2016-12-02 17:46     ` Tom Tromey
2016-12-02 18:11       ` Pedro Alves
2016-12-02 19:52         ` Tom Tromey
2016-12-02 23:45           ` Pedro Alves
2016-12-03  0:05   ` Pedro Alves
2016-12-13 13:13     ` Tom Tromey
2016-11-29  5:06 ` [RFA 3/8] Introduce and use gdb::unlinker Tom Tromey
2016-12-02 13:17   ` Pedro Alves
2016-11-29  5:06 ` [RFA 4/8] Remove make_cleanup_discard_psymtabs Tom Tromey
2016-12-02 14:21   ` Pedro Alves
2016-11-29  5:06 ` [RFA 8/8] Add constructor and destructor to demangle_parse_info Tom Tromey
2016-12-02 15:04   ` Pedro Alves
2016-12-13 13:50     ` Tom Tromey
2016-11-29  5:06 ` [RFA 7/8] Use unique_xmalloc_ptr in execute_gdb_command Tom Tromey
2016-11-29  5:22   ` Tom Tromey
2016-12-15  3:49     ` Tom Tromey
2016-12-20 17:48       ` Pedro Alves
2016-12-20 18:13         ` Tom Tromey
2016-12-23 20:01           ` Tom Tromey
2017-01-10 17:59             ` Pedro Alves
2017-01-10 19:22               ` Tom Tromey
2016-12-20 23:31         ` Tom Tromey
2016-12-20 23:56           ` Pedro Alves
2016-12-22 14:50             ` Tom Tromey
2016-12-22 15:09               ` Pedro Alves
2016-12-22 15:29                 ` Tom Tromey
2016-12-22 15:40                   ` Pedro Alves
2016-12-02 14:49   ` Pedro Alves
2016-12-13 13:30     ` Tom Tromey
2016-11-29  5:06 ` [RFA 6/8] Use value_freer in dwarf2_evaluate_loc_desc_full Tom Tromey
2016-12-02 14:45   ` Pedro Alves
2016-12-13 13:29     ` Tom Tromey
2016-12-20 14:49       ` Pedro Alves
2016-12-23 19:05         ` Tom Tromey
2016-12-23 19:59           ` Tom Tromey
2017-01-10 17:57             ` Pedro Alves
2016-12-23 19:59           ` Tom Tromey
2017-01-10 17:58             ` Pedro Alves
2016-11-29  5:06 ` [RFA 2/8] Use class to manage BFD reference counts Tom Tromey
2016-12-02 13:05   ` Pedro Alves
2016-12-13 13:26     ` Tom Tromey
2016-12-15  4:12       ` Tom Tromey
2016-12-20 18:18         ` Pedro Alves
2016-12-20 17:19       ` [pushed] gdb: Constify solib_find (Re: [RFA 2/8] Use class to manage BFD reference counts) Pedro Alves
2016-12-20 18:05         ` Tom Tromey
2016-11-29  5:06 ` [RFA 5/8] Add value_freer Tom Tromey
2016-12-02 14:24   ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1480395946-10924-2-git-send-email-tom@tromey.com \
    --to=tom@tromey.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).