diff options
author | Tom Tromey <tom@tromey.com> | 2016-11-20 17:48:31 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2017-01-10 19:14:09 -0700 |
commit | 50315b21779d71c172eb98a786a9b8281622e407 (patch) | |
tree | ff163e54508c6a8c959ff5f9f118debd34481bc0 /gdb/common | |
parent | fc4007c969ec4208fb7c7cee2f50211a9aa0f40f (diff) | |
download | gdb-50315b21779d71c172eb98a786a9b8281622e407.zip gdb-50315b21779d71c172eb98a786a9b8281622e407.tar.gz gdb-50315b21779d71c172eb98a786a9b8281622e407.tar.bz2 |
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.
Diffstat (limited to 'gdb/common')
-rw-r--r-- | gdb/common/gdb_ref_ptr.h | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/gdb/common/gdb_ref_ptr.h b/gdb/common/gdb_ref_ptr.h new file mode 100644 index 0000000..fbf4688 --- /dev/null +++ b/gdb/common/gdb_ref_ptr.h @@ -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 */ |