mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-23 12:09:49 +00:00
Add gdb_ref_ptr.h
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. 2017-01-10 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.
This commit is contained in:
parent
fc4007c969
commit
50315b2177
@ -1,3 +1,9 @@
|
||||
2017-01-10 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.
|
||||
|
||||
2017-01-10 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* utils.h (make_cleanup_htab_delete): Don't declare.
|
||||
|
215
gdb/common/gdb_ref_ptr.h
Normal file
215
gdb/common/gdb_ref_ptr.h
Normal file
@ -0,0 +1,215 @@
|
||||
/* 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 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. */
|
||||
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> &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 /* GDB_REF_PTR_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)
|
||||
static void incref (PyObject *ptr)
|
||||
{
|
||||
Py_INCREF (ptr);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
static void decref (PyObject *ptr)
|
||||
{
|
||||
Py_DECREF (ptr);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* 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 (PyObject *obj)
|
||||
{
|
||||
Py_XDECREF (m_obj);
|
||||
m_obj = obj;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
|
Loading…
Reference in New Issue
Block a user