1 Title: Object finalization
2 Tags: en, d, dgc, understanding the current gc, finalization, specs
4 I'm writing a trivial naive (but fully working) GC implementation. The idea is:
6 1. Improve my understanding about how a GC is written from the ground up
7 2. Ease the learning curve for other people wanting to learn how to write
9 3. Serve as documentation (will be **fully** documented)
10 4. Serve as a benchmarking base (to see how better is an implementation
11 compared to the dumbest and simplest implementation ever =)
13 There is a lot of literature on GC algorithms, but there is almost no
14 literature of the particularities on implementing a GC in D (how to handle the
15 stack, how finalize an object, etc.). The idea of this GC implementation is to
16 tackle this. The collection and allocation algorithms are really simple so you
17 can pay attention to the other stuff.
19 The exercise is already paying off. Implementing this GC I was able to see some
20 details I missed when I've done the `analysis of the current implementation`__.
22 __ https://proj.llucax.com.ar/blog/dgc/blog/tag/understanding%20the%20current%20gc
24 For example, I completely missed **finalization**. The GC stores for each cell
25 a flag that indicates when an object should be finalized, and when the memory
26 is swept it calls ``rt_finalize()`` to take care of the business. That was easy
27 to add to my toy GC implementation.
29 Then I was trying to decide if all memory should be released when the GC is
30 terminated or if I could let the OS do that. Then I remembered finalization,
31 so I realized I should at least call the finalizers for the live objects. So
32 I went see how the current implementation does that.
34 It turns out it just calls a full collection (you have an option to not collect
35 at all, or to collect excluding roots from the stack, using the undocumented
36 ``gc_setTermCleanupLevel()`` and ``gc_gsetTermCleanupLevel()`` functions). So
37 if there are still pointers in the static data or in the stack to objects with
38 finalizers, those finalizers are never called.
40 I've searched the specs__ and it's a documented *feature* that D **doesn't
41 guarantee** that all objects finalizers get called:
43 The garbage collector is not guaranteed to run the destructor for all
44 unreferenced objects. Furthermore, the order in which the garbage collector
45 calls destructors for unreference objects is not specified. This means that
46 when the garbage collector calls a destructor for an object of a class that
47 has members that are references to garbage collected objects, those
48 references may no longer be valid. This means that destructors cannot
49 reference sub objects.
51 __ http://www.digitalmars.com/d/1.0/class.html#destructors
53 I knew that ordering was not guaranteed so you can't call other finalizer in
54 a finalizer (and that make a lot of sense), but I didn't knew about the other
55 stuff. This is great for GC implementors but not so nice for GC users ;)
57 I know that the GC, being conservative, has a lot of limitations, but I think
58 this one is not completely necessary. When the program ends, it should be
59 fairly safe to call all the finalizers for the live objects, referenced or not.
61 In this scheme, finalization is as reliable as UDP__ =)
63 __ http://en.wikipedia.org/wiki/User_Datagram_Protocol
65 .. vim: set et sw=4 sts=4 :