Introduce py-ref.h
This patch introduces class gdbpy_ref, which is a sort of smart pointer that owns a single Python reference to a PyObject. This class acts a bit like unique_ptr, but also a bit like shared_ptr (in that copies do what you might expect); I considered going solely with unique_ptr but it seemed quite strange to have a unique_ptr that actually manages a shared resource. Subsequent patches use this new class to simplify logic in the Python layer. 2017-01-10 Tom Tromey <tom@tromey.com> * python/py-ref.h: New file.
This commit is contained in:
parent
0b67023188
commit
a68ff33e0d
2 changed files with 163 additions and 0 deletions
|
@ -1,3 +1,7 @@
|
||||||
|
2017-01-10 Tom Tromey <tom@tromey.com>
|
||||||
|
|
||||||
|
* python/py-ref.h: New file.
|
||||||
|
|
||||||
2017-01-10 Simon Marchi <simon.marchi@ericsson.com>
|
2017-01-10 Simon Marchi <simon.marchi@ericsson.com>
|
||||||
|
|
||||||
* cli-out.c (cli_ui_out::do_redirect): Change return type to
|
* cli-out.c (cli_ui_out::do_redirect): Change return type to
|
||||||
|
|
159
gdb/python/py-ref.h
Normal file
159
gdb/python/py-ref.h
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/* Python reference-holding 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_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.
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* 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 ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* GDB_PYTHON_REF_H */
|
Loading…
Add table
Add a link
Reference in a new issue