Code

Node tool: special case node duplication for endnodes - select new endnode
[inkscape.git] / src / gc-finalized.h
index a31155653e69ba19f45146f82f27847639af3383..4e09d6f8b1770388c316eca58f0f2a9d7dcba709 100644 (file)
@@ -23,7 +23,7 @@ namespace Inkscape {
 
 namespace GC {
 
-/* @brief a mix-in ensuring that a object's destructor will get called before
+/* @brief A mix-in ensuring that an object's destructor will get called before
  *        the garbage collector destroys it
  *
  * Normally, the garbage collector does not call destructors before destroying
@@ -39,36 +39,28 @@ namespace GC {
  *      happens.
  *
  *      The best way to limit this effect is to only make "leaf" objects
- *      (i.e. those that don't point to other finalizaable objects)
- *      finalizable, or if the object also derives from GC::Managed<>,
- *      use GC::Managed<>::clearOnceInaccessible to register those links
- *      to be cleared once the object is made inacecssible (and before it's
- *      finalized).
+ *      (i.e. those that don't point to other finalizable objects)
+ *      finalizable, and otherwise use GC::soft_ptr<> instead of a regular
+ *      pointer for "backreferences" (e.g. parent pointers in a tree
+ *      structure), so that those references can be cleared to break any
+ *      finalization cycles.
  *
- *      In a tree structure that has parent links and finalized nodes,
- *      you will almost always want to do this with the parent links
- *      if you can't avoid having them.
- *
- *      @see Inkscape::GC::Managed<>::clearOnceInaccessible
- *      @see Inkscape::GC::Managed<>::cancelClearOnceInacessible
+ *      @see Inkscape::GC::soft_ptr<>
  *
  *   2. Because there is no guarantee when the collector will destroy
- *      objects, there is no guarantee when the destructor will get called.
- *
- *      It may not get called until the very end of the program, or never.
+ *      objects, it is impossible to tell in advance when the destructor
+ *      will get called. It may not get called until the very end
+ *      of the program, or ever.
  *
  *   3. If allocated in arrays, only the first object in the array will
  *      have its destructor called, unless you make other arrangements by
  *      registering your own finalizer instead.
  *
- *   4. Similarly, making multiple GC::Finalized-derived objects members
- *      of a non-finalized but garbage-collected object generally won't
- *      work unless you take care of registering finalizers yourself.
- *
- * [n.b., by "member", I mean an actual by-value-member of a type that
- *  derives from GC::Finalized, not simply a member that's a pointer or a
- *  reference to such a type]
- *
+ *   4. Similarly, putting a finalized object as a member in another
+ *      garbage collected but non-finalized object will cause the member
+ *      object's destructor not to be called when the parent object is
+ *      collected, unless you register the finalizer yourself (by "member"
+ *      we mean an actual by-value member, not a reference or a pointer).
  */
 class Finalized {
 public:
@@ -119,9 +111,7 @@ public:
 
 private:
     /// invoke the destructor for an object given a base and offset pair
-    static void _invoke_dtor(void *base, void *offset) {
-        _unoffset(base, offset)->~Finalized();
-    }
+    static void _invoke_dtor(void *base, void *offset);
 
     /// turn 'this' pointer into an offset-from-base-address (stored as void *)
     static void *_offset(void *base, Finalized *self) {
@@ -152,4 +142,4 @@ private:
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :