summaryrefslogtreecommitdiff
path: root/src/irr_ptr.h
diff options
context:
space:
mode:
authorVitaliy <numzer0@yandex.ru>2021-01-24 17:40:34 +0300
committerGitHub <noreply@github.com>2021-01-24 14:40:34 +0000
commit8dae7b47fcc1c26251c8006efbc9ee8af152f87a (patch)
tree7d4d8590b7eb78de1d59705ac16d389de99d239b /src/irr_ptr.h
parentad9adcb88444b4a7063d5c2f5debd85729e8ce42 (diff)
downloadminetest-8dae7b47fcc1c26251c8006efbc9ee8af152f87a.tar.gz
minetest-8dae7b47fcc1c26251c8006efbc9ee8af152f87a.tar.bz2
minetest-8dae7b47fcc1c26251c8006efbc9ee8af152f87a.zip
Improve irr_ptr (#10808)
Diffstat (limited to 'src/irr_ptr.h')
-rw-r--r--src/irr_ptr.h89
1 files changed, 76 insertions, 13 deletions
diff --git a/src/irr_ptr.h b/src/irr_ptr.h
index 5022adb9d..42b409676 100644
--- a/src/irr_ptr.h
+++ b/src/irr_ptr.h
@@ -27,9 +27,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
* It should only be used for user-managed objects, i.e. those created with
* the @c new operator or @c create* functions, like:
* `irr_ptr<scene::IMeshBuffer> buf{new scene::SMeshBuffer()};`
+ * The reference counting is *not* balanced as new objects have reference
+ * count set to one, and the @c irr_ptr constructor (and @c reset) assumes
+ * ownership of that reference.
*
- * It should *never* be used for engine-managed objects, including
- * those created with @c addTexture and similar methods.
+ * It shouldn’t be used for engine-managed objects, including those created
+ * with @c addTexture and similar methods. Constructing @c irr_ptr directly
+ * from such object is a bug and may lead to a crash. Indirect construction
+ * is possible though; see the @c grab free function for details and use cases.
*/
template <class ReferenceCounted,
class = typename std::enable_if<std::is_base_of<IReferenceCounted,
@@ -38,16 +43,6 @@ class irr_ptr
{
ReferenceCounted *value = nullptr;
- /** Drops stored pointer replacing it with the given one.
- * @note Copy semantics: reference counter *is* increased.
- */
- void grab(ReferenceCounted *object)
- {
- if (object)
- object->grab();
- reset(object);
- }
-
public:
irr_ptr() {}
@@ -71,8 +66,10 @@ public:
reset(b.release());
}
- /** Constructs a shared pointer out of a plain one
+ /** Constructs a shared pointer out of a plain one to control object lifetime.
+ * @param object The object, usually returned by some @c create* function.
* @note Move semantics: reference counter is *not* increased.
+ * @warning Never wrap any @c add* function with this!
*/
explicit irr_ptr(ReferenceCounted *object) noexcept { reset(object); }
@@ -134,4 +131,70 @@ public:
value->drop();
value = object;
}
+
+ /** Drops stored pointer replacing it with the given one.
+ * @note Copy semantics: reference counter *is* increased.
+ */
+ void grab(ReferenceCounted *object) noexcept
+ {
+ if (object)
+ object->grab();
+ reset(object);
+ }
};
+
+// clang-format off
+// ^ dislikes long lines
+
+/** Constructs a shared pointer as a *secondary* reference to an object
+ *
+ * This function is intended to make a temporary reference to an object which
+ * is owned elsewhere so that it is not destroyed too early. To acheive that
+ * it does balanced reference counting, i.e. reference count is increased
+ * in this function and decreased when the returned pointer is destroyed.
+ */
+template <class ReferenceCounted>
+irr_ptr<ReferenceCounted> grab(ReferenceCounted *object) noexcept
+{
+ irr_ptr<ReferenceCounted> ptr;
+ ptr.grab(object);
+ return ptr;
+}
+
+template <typename ReferenceCounted>
+bool operator==(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
+{
+ return a.get() == b.get();
+}
+
+template <typename ReferenceCounted>
+bool operator==(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
+{
+ return a.get() == b;
+}
+
+template <typename ReferenceCounted>
+bool operator==(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
+{
+ return a == b.get();
+}
+
+template <typename ReferenceCounted>
+bool operator!=(const irr_ptr<ReferenceCounted> &a, const irr_ptr<ReferenceCounted> &b) noexcept
+{
+ return a.get() != b.get();
+}
+
+template <typename ReferenceCounted>
+bool operator!=(const irr_ptr<ReferenceCounted> &a, const ReferenceCounted *b) noexcept
+{
+ return a.get() != b;
+}
+
+template <typename ReferenceCounted>
+bool operator!=(const ReferenceCounted *a, const irr_ptr<ReferenceCounted> &b) noexcept
+{
+ return a != b.get();
+}
+
+// clang-format on