From patchwork Tue Nov 29 05:05:39 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 18033 Received: (qmail 15631 invoked by alias); 29 Nov 2016 05:06:16 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 14811 invoked by uid 89); 29 Nov 2016 05:06:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=H*F:U*tom, borrowed, H*m:10924, H*r:4.86_1 X-HELO: gproxy9-pub.mail.unifiedlayer.com Received: from gproxy9-pub.mail.unifiedlayer.com (HELO gproxy9-pub.mail.unifiedlayer.com) (69.89.20.122) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with SMTP; Tue, 29 Nov 2016 05:06:00 +0000 Received: (qmail 26148 invoked by uid 0); 29 Nov 2016 05:05:58 -0000 Received: from unknown (HELO CMOut01) (10.0.90.82) by gproxy9.mail.unifiedlayer.com with SMTP; 29 Nov 2016 05:05:58 -0000 Received: from box522.bluehost.com ([74.220.219.122]) by CMOut01 with id Dh5t1u0092f2jeq01h5wPN; Mon, 28 Nov 2016 22:05:56 -0700 X-Authority-Analysis: v=2.1 cv=E8Je+8tl c=1 sm=1 tr=0 a=GsOEXm/OWkKvwdLVJsfwcA==:117 a=GsOEXm/OWkKvwdLVJsfwcA==:17 a=L9H7d07YOLsA:10 a=9cW_t1CCXrUA:10 a=s5jvgZ67dGcA:10 a=L24OOQBejmoA:10 a=zstS-IiYAAAA:8 a=mDV3o1hIAAAA:8 a=fXoX8jPsWLVnJmP79-sA:9 a=4G6NA9xxw8l3yy4pmD5M:22 a=_FVE-zBwftR9WsbkzFJk:22 Received: from 71-218-195-233.hlrn.qwest.net ([71.218.195.233]:46172 helo=bapiya.Home) by box522.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.86_1) (envelope-from ) id 1cBac6-0000aB-FH; Mon, 28 Nov 2016 22:05:54 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [RFA 1/8] Add gdb_ref_ptr.h Date: Mon, 28 Nov 2016 22:05:39 -0700 Message-Id: <1480395946-10924-2-git-send-email-tom@tromey.com> In-Reply-To: <1480395946-10924-1-git-send-email-tom@tromey.com> References: <1480395946-10924-1-git-send-email-tom@tromey.com> X-BWhitelist: no X-Exim-ID: 1cBac6-0000aB-FH X-Source-Sender: 71-218-195-233.hlrn.qwest.net (bapiya.Home) [71.218.195.233]:46172 X-Source-Auth: tom+tromey.com X-Email-Count: 2 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTIyLmJsdWVob3N0LmNvbQ== 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 * 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 + * 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 + * 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 . */ + +#ifndef GDB_REF_PTR_H +#define GDB_REF_PTR_H + +#include + +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 +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 +inline bool operator== (const ref_ptr &self, + const ref_ptr &other) +{ + return self.get () == other.get (); +} + +template +inline bool operator== (const ref_ptr &self, const T *other) +{ + return self.get () == other; +} + +template +inline bool operator== (const ref_ptr &self, const std::nullptr_t) +{ + return self.get () == nullptr; +} + +template +inline bool operator== (const T *self, const ref_ptr &other) +{ + return self == other.get (); +} + +template +inline bool operator== (const std::nullptr_t, const ref_ptr &other) +{ + return nullptr == other.get (); +} + +template +inline bool operator!= (const ref_ptr &self, + const ref_ptr &other) +{ + return self.get () != other.get (); +} + +template +inline bool operator!= (const ref_ptr &self, const T *other) +{ + return self.get () != other; +} + +template +inline bool operator!= (const ref_ptr &self, const std::nullptr_t) +{ + return self.get () != nullptr; +} + +template +inline bool operator!= (const T *self, const ref_ptr &other) +{ + return self != other.get (); +} + +template +inline bool operator!= (const std::nullptr_t, const ref_ptr &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 gdbpy_ref; #endif /* GDB_PYTHON_REF_H */