summaryrefslogtreecommitdiffstats
path: root/src/gc-anchored.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gc-anchored.h')
-rw-r--r--src/gc-anchored.h177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/gc-anchored.h b/src/gc-anchored.h
new file mode 100644
index 0000000..8a7b2d7
--- /dev/null
+++ b/src/gc-anchored.h
@@ -0,0 +1,177 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * * Copyright (C) 2004 MenTaLguY
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#ifndef SEEN_INKSCAPE_GC_ANCHORED_H
+#define SEEN_INKSCAPE_GC_ANCHORED_H
+
+#include "inkgc/gc-managed.h"
+
+namespace Inkscape {
+
+namespace GC {
+
+/**
+ * A base class for anchored objects.
+ *
+ * Objects are managed by our mark-and-sweep collector, but are anchored
+ * against garbage collection so long as their reference count is nonzero.
+ *
+ * Object and member destructors will not be called on destruction
+ * unless a subclass also inherits from Inkscape::GC::Finalized.
+ *
+ * New instances of anchored objects should be created using the C++ new
+ * operator. Under normal circumstances they should not be created on
+ * the stack.
+ *
+ * A newly created anchored object begins with a refcount of one, and
+ * will not be collected unless the refcount is zero.
+ *
+ * NOTE: If you create an object yourself, it is already anchored for
+ * you. You do not need to anchor it a second time.
+ *
+ * Note that a cycle involving an anchored object (with nonzero refcount)
+ * cannot be collected. To avoid this, don't increment refcounts for
+ * pointers between two GC-managed objects.
+ *
+ * @see Inkscape::GC::Managed
+ * @see Inkscape::GC::Finalized
+ * @see Inkscape::GC::anchor
+ * @see Inkscape::GC::release
+ */
+
+class Anchored {
+public:
+ void anchor() const;
+ void release() const;
+
+ // for debugging
+ unsigned _anchored_refcount() const {
+ return ( _anchor ? _anchor->refcount : 0 );
+ }
+
+ Anchored(Anchored const &) = delete; // no copy
+ void operator=(Anchored const &) = delete; // no assign
+
+protected:
+ Anchored() : _anchor(nullptr) { anchor(); } // initial refcount of one
+ virtual ~Anchored() = default;
+
+private:
+ struct Anchor : public Managed<SCANNED, MANUAL> {
+ Anchor() : refcount(0),base(nullptr) {}
+ Anchor(Anchored const *obj) : refcount(0) {
+ base = Core::base(const_cast<Anchored *>(obj));
+ }
+ int refcount;
+ void *base;
+ };
+
+ mutable Anchor *_anchor;
+
+ Anchor *_new_anchor() const;
+ void _free_anchor(Anchor *anchor) const;
+};
+
+/**
+ * @brief Increments the reference count of a anchored object.
+ *
+ * This function template generates functions which take
+ * a reference to a anchored object of a given type, increment
+ * that object's reference count, and return a reference to the
+ * object of the same type as the function's parameter.
+ *
+ * @param m a reference to a anchored object
+ *
+ * @return the reference to the object
+ */
+template <typename R>
+static R &anchor(R &r) {
+ static_cast<Anchored const &>(const_cast<R const &>(r)).anchor();
+ return r;
+}
+
+/**
+ * @brief Increments the reference count of a anchored object.
+ *
+ * This function template generates functions which take
+ * a pointer to a anchored object of a given type, increment
+ * that object's reference count, and return a pointer to the
+ * object of the same type as the function's parameter.
+ *
+ * @param m a pointer to anchored object
+ *
+ * @return the pointer to the object
+ */
+template <typename R>
+static R *anchor(R *r) {
+ static_cast<Anchored const *>(const_cast<R const *>(r))->anchor();
+ return r;
+}
+
+/**
+ * @brief Decrements the reference count of a anchored object.
+ *
+ * This function template generates functions which take
+ * a reference to a anchored object of a given type, increment
+ * that object's reference count, and return a reference to the
+ * object of the same type as the function's parameter.
+ *
+ * The return value is safe to use since the object, even if
+ * its refcount has reached zero, will not actually be collected
+ * until there are no references to it in local variables or
+ * parameters.
+ *
+ * @param m a reference to a anchored object
+ *
+ * @return the reference to the object
+ */
+template <typename R>
+static R &release(R &r) {
+ static_cast<Anchored const &>(const_cast<R const &>(r)).release();
+ return r;
+}
+
+/**
+ * @brief Decrements the reference count of a anchored object.
+ *
+ * This function template generates functions which take
+ * a pointer to a anchored object of a given type, increment
+ * that object's reference count, and return a pointer to the
+ * object of the same type as the function's parameter.
+ *
+ * The return value is safe to use since the object, even if
+ * its refcount has reached zero, will not actually be collected
+ * until there are no references to it in local variables or
+ * parameters.
+ *
+ * @param m a pointer to a anchored object
+ *
+ * @return the pointer to the object
+ */
+template <typename R>
+static R *release(R *r) {
+ static_cast<Anchored const *>(const_cast<R const *>(r))->release();
+ return r;
+}
+
+}
+
+}
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :