home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / lang / cplus / 13003 < prev    next >
Encoding:
Text File  |  1992-08-27  |  5.8 KB  |  127 lines

  1. Path: sparky!uunet!synaptx!synaptics.com!daveg
  2. From: daveg@synaptics.com (Dave Gillespie)
  3. Newsgroups: comp.lang.c++
  4. Subject: Re: Garbage Collection for C++
  5. Message-ID: <DAVEG.92Aug28004331@synaptx.synaptics.com>
  6. Date: 28 Aug 92 07:43:31 GMT
  7. References: <DAVEG.92Aug20043156@synaptx.synaptics.com> <28623@vedge.UUCP>
  8. Sender: daveg@synaptx.Synaptics.Com
  9. Organization: Synaptics, Inc., San Jose, CA
  10. Lines: 114
  11. In-reply-to: hendrik@vedge.UUCP's message of 27 Aug 92 18:33:04 GMT
  12.  
  13. In article <28623@vedge.UUCP> hendrik@vedge.UUCP (Hendrik Boom) writes:
  14. >> I did; as far as I can tell, the GC has to call destructors, and it's
  15.  
  16. > One of my nightmares in a Lisp garbage collector is the destructor
  17. > from Hell that retrieves otherwise moribund objects and makes them
  18. > accessible again.  Do we have to do another garbage collection to see if
  19. > objects are really free?  And if they are, do we have to call
  20. > the destructor from hell again? and again? and again? and again?
  21.  
  22. Your description is more dramatic than clear :-), but it brings to
  23. mind an example where garbage collection could be troublesome in C++.
  24. Is this what you were thinking of?
  25.  
  26.    class D *orphanedThing;
  27.    class C {
  28.      D *thing;
  29.      ~C() { orphanedThing = thing; }
  30.    };
  31.  
  32. Now suppose there is a C object which has become garbage, and there
  33. is a D object that is unreferenced except through that C object's
  34. "thing" member.  The GC is justified in noting that the C object is
  35. garbage and destroying it, but it can't go on to conclude that the
  36. D object is garbage since the destructor is going to leave behind
  37. another reference to it.
  38.  
  39. Lisp objects generally don't have "destructors", at least not ones
  40. with visible side effects.  In Lisp, if the only references to an
  41. object are from other garbage objects, that object is also garbage.
  42. If Lisp couldn't rely on this, a 1000-element garbage linked list
  43. could only be freed one link at a time, requiring 1000 successive
  44. GC's to free the whole list!  (Thus resulting in the fire and
  45. brimstone to which Hendrik alludes.)
  46.  
  47.  
  48. This all reminds me of the idea of "finalizations" in Lisp, a
  49. simple-sounding and very useful concept that turns out to be a
  50. horrible quagmire of complications when it is implemented.
  51.  
  52. Basically, a finalization is a property that can be attached to
  53. any allocated object, which is a function to be called to clean up
  54. when that object is garbage-collected.  In other words, it's a
  55. destructor.
  56.  
  57. As well as the problem Hendrik describes, there is the more basic
  58. problem of when to call the finalization:  Most Lisps shut down
  59. completely during GC and are not able to call user-defined
  60. functions until the GC is completely finished; if you have a
  61. compacting garbage collector, how do you compact across an
  62. object if you haven't called its finalization yet?
  63.  
  64. The only Lisp system I've used which implements finalizations is
  65. Allegro Common Lisp.  They solve these problems by freeing objects
  66. with finalizations in two stages.  When the GC first determines
  67. that an object is garbage, and the object has a finalization, the GC
  68. doesn't actually destroy it; instead, it adds the object to a list
  69. of things to be finalized, and then *removes the finalization from
  70. the object*.  When GC finishes, it finalizes these objects and
  71. removes them from the list before going on with the main program.
  72. Since the objects' finalizations have been removed, the *next* GC
  73. will finally destroy them.  If for some reason the finalization
  74. code saves away a reference to a part of the object, or even to the
  75. object itself, the next GC will see the new reference and do the
  76. right thing.
  77.  
  78. Even if the next GC occurs during the finalization step from the
  79. previous GC, you're safe because the yet-to-be-finalized objects
  80. are not garbage yet---they're referenced by the finalization list
  81. itself!
  82.  
  83. Hendrik's issue is solved by making garbage-ness transitive only
  84. for things without destructors.  If an object has a destructor,
  85. it is not deleted by the first GC so the things it points to are
  86. not yet garbage.
  87.  
  88.  
  89. If you made a linked list of N things each of which had destructors,
  90. it would still take N GC's to delete the list, but the idea is that
  91. destructors (finalizations) would only be used for the kinds of
  92. things that are not used in big lists.  For example, a finalization
  93. might close a file that was held open by the object; rarely would
  94. you have a linked list of 1000 objects each holding open a file!
  95. (And where the links are in the objects themselves; a conventional
  96. Lisp list of pointers to finalizable objects would have no problem,
  97. because the cons cells themselves have no finalizations and so can
  98. be collected all at once.)
  99.  
  100. A C++ garbage collector could make itself destructor-safe using
  101. the same strategy.  When the GC finds an object is garbage and the
  102. object has a destructor, it simply calls the destructor and then
  103. somehow sets a flag showing that the object has effectively been
  104. converted to raw bits.  The next GC will finally collect the
  105. object's memory.  I doubt such a flag would be difficult to add;
  106. allocated objects would need a place to record enough RTTI to find
  107. the proper destructor anyway.
  108.  
  109. But wait---don't most classes have destructors?  Yes, at present,
  110. but I claim that GC would render most destructors obsolete.
  111. Destructors tend to be used for cleaning up auxiliary memory, a
  112. task which would be automated by GC.  Destructors in a C++ with
  113. GC would be just as rare as finalizations are in Lisp.
  114.  
  115. A compiler that could prove a given destructor had no (pointer)
  116. side effects could optimize by instructing the GC to call the
  117. destructor and delete the object immediately.  For example, a
  118. destructor which only calls close(), or only adjusts some profiling
  119. statistics, could do this.  But is only an optimization; a simple
  120. compiler could treat all destructors the same.
  121.  
  122.                                 -- Dave
  123. --
  124. Dave Gillespie
  125.   daveg@synaptics.com, uunet!synaptx!daveg
  126.   or: daveg@csvax.cs.caltech.edu
  127.