Code

introduce lifecycle stuff which will replace libgc
authormental <mental@users.sourceforge.net>
Thu, 15 May 2008 17:01:15 +0000 (17:01 +0000)
committermental <mental@users.sourceforge.net>
Thu, 15 May 2008 17:01:15 +0000 (17:01 +0000)
src/Makefile_insert
src/lifecycle.h [new file with mode: 0644]

index f39ad098fd17258f1ad4b63db9d556b454c74ae8..62d6b92ce27fade88dc07c8ea0b9321060e2a1fe 100644 (file)
@@ -327,6 +327,7 @@ libinkpost_a_SOURCES =      \
        gradient-chemistry.cpp gradient-chemistry.h     \
        ink-action.cpp  \
        ink-action.h    \
+       lifecycle.h     \
        memeq.h \
        round.h \
        streq.h \
diff --git a/src/lifecycle.h b/src/lifecycle.h
new file mode 100644 (file)
index 0000000..7e37bd8
--- /dev/null
@@ -0,0 +1,134 @@
+/** \file
+ * Inkscape::Lifecycle - automatic object lifecycle management
+ *
+ * Copyright 2008 MenTaLguY <mental@rydia.net>
+ *
+ * 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 2
+ * of the License, or (at your option) any later version.
+ *
+ * See the file COPYING for details.
+ *
+ */
+
+#ifndef SEEN_INKSCAPE_LIFECYCLE_H
+#define SEEN_INKSCAPE_LIFECYCLE_H
+
+#include <glib/gtypes.h>
+#include <glib/gatomic.h>
+
+namespace Inkscape {
+namespace Lifecycle {
+
+class BaseManagedPtr;
+
+// Abstract base class for managed objects
+class AbstractManaged {
+public:
+    AbstractManaged() {}
+    virtual ~AbstractManaged() {}
+protected:
+    virtual void managedAddReference() const=0;
+    virtual void managedRemoveReference() const=0;
+    friend class BaseManagedPtr;
+private:
+    AbstractManaged(AbstractManaged &); // no copy
+    void operator=(AbstractManaged &); // no assign
+};
+
+// Base class for managed pointers; not intended for direct use
+class BaseManagedPtr {
+protected:
+    BaseManagedPtr() : ptr(NULL) {}
+    BaseManagedPtr(AbstractManaged const *managed) : ptr(NULL) {
+        set(managed);
+    }
+    BaseManagedPtr(BaseManagedPtr const &other) : ptr(NULL) {
+        set(other.ptr);
+    }
+
+    AbstractManaged const *get() const { return ptr; }
+    void set(AbstractManaged const *managed) {
+        if (managed) {
+            ptr->managedAddReference();
+        }
+        if (ptr) {
+            ptr->managedRemoveReference();
+        }
+        ptr = managed;
+    }
+
+private:
+    AbstractManaged const *ptr;
+};
+
+// Type-safe managed pointer
+template <typename T>
+class ManagedPtr : public BaseManagedPtr {
+public:
+    ManagedPtr() : BaseManagedPtr() {}
+    ManagedPtr(T *managed) : BaseManagedPtr(managed) {}
+    ManagedPtr(ManagedPtr const &other) : BaseManagedPtr(other) {}
+
+    operator T *() const { return get_recast(); }
+    T &operator*() const { return *get_recast(); }
+    T *operator->() const { return get_recast(); }
+    ManagedPtr &operator=(T *managed) {
+        set(managed);
+        return *this;
+    }
+    ManagedPtr &operator=(ManagedPtr const &other) {
+        set(other.get());
+        return *this;
+    }
+
+private:
+    T *get_recast() const {
+        return const_cast<T *>(static_cast<T const *>(get()));
+    }
+};
+
+// Dummy implementation of AbstractManaged to ease migration
+class DummyManaged : public virtual AbstractManaged {
+protected:
+    virtual void managedAddReference() const {}
+    virtual void managedRemoveReference() const {}
+};
+
+// Straightforward refcounting implementation of AbstractManaged
+class SimpleManaged : public virtual AbstractManaged {
+protected:
+    SimpleManaged() : refcount(0) {}
+    virtual ~SimpleManaged() {}
+
+    virtual void managedAddReference() const {
+        g_atomic_int_inc(&refcount);
+    }
+    virtual void managedRemoveReference() const {
+        if (g_atomic_int_dec_and_test(&refcount)) {
+            const_cast<SimpleManaged *>(this)->managedDispose();
+        }
+    }
+    virtual void managedDispose() {
+        delete this;
+    }
+
+private:
+    mutable volatile gint refcount;
+};
+
+}
+}
+
+#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:encoding=utf-8:textwidth=99 :