weakpointer.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #ifndef _weakpointer_h_
  2. #define _weakpointer_h_
  3. /****************************************************************************
  4. WeakPointer and CleanUp
  5. Copyright (c) 1991 by Xerox Corporation. All rights reserved.
  6. THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  7. OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  8. Permission is hereby granted to copy this code for any purpose,
  9. provided the above notices are retained on all copies.
  10. ****************************************************************************/
  11. /****************************************************************************
  12. WeakPointer
  13. A weak pointer is a pointer to a heap-allocated object that doesn't
  14. prevent the object from being garbage collected. Weak pointers can be
  15. used to track which objects haven't yet been reclaimed by the
  16. collector. A weak pointer is deactivated when the collector discovers
  17. its referent object is unreachable by normal pointers (reachability
  18. and deactivation are defined more precisely below). A deactivated weak
  19. pointer remains deactivated forever.
  20. ****************************************************************************/
  21. template< class T > class WeakPointer {
  22. public:
  23. WeakPointer( T* t = 0 )
  24. /* Constructs a weak pointer for *t. t may be null. It is an error
  25. if t is non-null and *t is not a collected object. */
  26. {impl = _WeakPointer_New( t );}
  27. T* Pointer()
  28. /* wp.Pointer() returns a pointer to the referent object of wp or
  29. null if wp has been deactivated (because its referent object
  30. has been discovered unreachable by the collector). */
  31. {return (T*) _WeakPointer_Pointer( this->impl );}
  32. int operator==( WeakPointer< T > wp2 )
  33. /* Given weak pointers wp1 and wp2, if wp1 == wp2, then wp1 and
  34. wp2 refer to the same object. If wp1 != wp2, then either wp1
  35. and wp2 don't refer to the same object, or if they do, one or
  36. both of them has been deactivated. (Note: If objects t1 and t2
  37. are never made reachable by their clean-up functions, then
  38. WeakPointer<T>(t1) == WeakPointer<T>(t2) if and only t1 == t2.) */
  39. {return _WeakPointer_Equal( this->impl, wp2.impl );}
  40. int Hash()
  41. /* Returns a hash code suitable for use by multiplicative- and
  42. division-based hash tables. If wp1 == wp2, then wp1.Hash() ==
  43. wp2.Hash(). */
  44. {return _WeakPointer_Hash( this->impl );}
  45. private:
  46. void* impl;
  47. };
  48. /*****************************************************************************
  49. CleanUp
  50. A garbage-collected object can have an associated clean-up function
  51. that will be invoked some time after the collector discovers the
  52. object is unreachable via normal pointers. Clean-up functions can be
  53. used to release resources such as open-file handles or window handles
  54. when their containing objects become unreachable. If a C++ object has
  55. a non-empty explicit destructor (i.e. it contains programmer-written
  56. code), the destructor will be automatically registered as the object's
  57. initial clean-up function.
  58. There is no guarantee that the collector will detect every unreachable
  59. object (though it will find almost all of them). Clients should not
  60. rely on clean-up to cause some action to occur immediately -- clean-up
  61. is only a mechanism for improving resource usage.
  62. Every object with a clean-up function also has a clean-up queue. When
  63. the collector finds the object is unreachable, it enqueues it on its
  64. queue. The clean-up function is applied when the object is removed
  65. from the queue. By default, objects are enqueued on the garbage
  66. collector's queue, and the collector removes all objects from its
  67. queue after each collection. If a client supplies another queue for
  68. objects, it is his responsibility to remove objects (and cause their
  69. functions to be called) by polling it periodically.
  70. Clean-up queues allow clean-up functions accessing global data to
  71. synchronize with the main program. Garbage collection can occur at any
  72. time, and clean-ups invoked by the collector might access data in an
  73. inconsistent state. A client can control this by defining an explicit
  74. queue for objects and polling it at safe points.
  75. The following definitions are used by the specification below:
  76. Given a pointer t to a collected object, the base object BO(t) is the
  77. value returned by new when it created the object. (Because of multiple
  78. inheritance, t and BO(t) may not be the same address.)
  79. A weak pointer wp references an object *t if BO(wp.Pointer()) ==
  80. BO(t).
  81. ***************************************************************************/
  82. template< class T, class Data > class CleanUp {
  83. public:
  84. static void Set( T* t, void c( Data* d, T* t ), Data* d = 0 )
  85. /* Sets the clean-up function of object BO(t) to be <c, d>,
  86. replacing any previously defined clean-up function for BO(t); c
  87. and d can be null, but t cannot. Sets the clean-up queue for
  88. BO(t) to be the collector's queue. When t is removed from its
  89. clean-up queue, its clean-up will be applied by calling c(d,
  90. t). It is an error if *t is not a collected object. */
  91. {_CleanUp_Set( t, c, d );}
  92. static void Call( T* t )
  93. /* Sets the new clean-up function for BO(t) to be null and, if the
  94. old one is non-null, calls it immediately, even if BO(t) is
  95. still reachable. Deactivates any weak pointers to BO(t). */
  96. {_CleanUp_Call( t );}
  97. class Queue {public:
  98. Queue()
  99. /* Constructs a new queue. */
  100. {this->head = _CleanUp_Queue_NewHead();}
  101. void Set( T* t )
  102. /* q.Set(t) sets the clean-up queue of BO(t) to be q. */
  103. {_CleanUp_Queue_Set( this->head, t );}
  104. int Call()
  105. /* If q is non-empty, q.Call() removes the first object and
  106. calls its clean-up function; does nothing if q is
  107. empty. Returns true if there are more objects in the
  108. queue. */
  109. {return _CleanUp_Queue_Call( this->head );}
  110. private:
  111. void* head;
  112. };
  113. };
  114. /**********************************************************************
  115. Reachability and Clean-up
  116. An object O is reachable if it can be reached via a non-empty path of
  117. normal pointers from the registers, stacks, global variables, or an
  118. object with a non-null clean-up function (including O itself),
  119. ignoring pointers from an object to itself.
  120. This definition of reachability ensures that if object B is accessible
  121. from object A (and not vice versa) and if both A and B have clean-up
  122. functions, then A will always be cleaned up before B. Note that as
  123. long as an object with a clean-up function is contained in a cycle of
  124. pointers, it will always be reachable and will never be cleaned up or
  125. collected.
  126. When the collector finds an unreachable object with a null clean-up
  127. function, it atomically deactivates all weak pointers referencing the
  128. object and recycles its storage. If object B is accessible from object
  129. A via a path of normal pointers, A will be discovered unreachable no
  130. later than B, and a weak pointer to A will be deactivated no later
  131. than a weak pointer to B.
  132. When the collector finds an unreachable object with a non-null
  133. clean-up function, the collector atomically deactivates all weak
  134. pointers referencing the object, redefines its clean-up function to be
  135. null, and enqueues it on its clean-up queue. The object then becomes
  136. reachable again and remains reachable at least until its clean-up
  137. function executes.
  138. The clean-up function is assured that its argument is the only
  139. accessible pointer to the object. Nothing prevents the function from
  140. redefining the object's clean-up function or making the object
  141. reachable again (for example, by storing the pointer in a global
  142. variable).
  143. If the clean-up function does not make its object reachable again and
  144. does not redefine its clean-up function, then the object will be
  145. collected by a subsequent collection (because the object remains
  146. unreachable and now has a null clean-up function). If the clean-up
  147. function does make its object reachable again and a clean-up function
  148. is subsequently redefined for the object, then the new clean-up
  149. function will be invoked the next time the collector finds the object
  150. unreachable.
  151. Note that a destructor for a collected object cannot safely redefine a
  152. clean-up function for its object, since after the destructor executes,
  153. the object has been destroyed into "raw memory". (In most
  154. implementations, destroying an object mutates its vtbl.)
  155. Finally, note that calling delete t on a collected object first
  156. deactivates any weak pointers to t and then invokes its clean-up
  157. function (destructor).
  158. **********************************************************************/
  159. extern "C" {
  160. void* _WeakPointer_New( void* t );
  161. void* _WeakPointer_Pointer( void* wp );
  162. int _WeakPointer_Equal( void* wp1, void* wp2 );
  163. int _WeakPointer_Hash( void* wp );
  164. void _CleanUp_Set( void* t, void (*c)( void* d, void* t ), void* d );
  165. void _CleanUp_Call( void* t );
  166. void* _CleanUp_Queue_NewHead ();
  167. void _CleanUp_Queue_Set( void* h, void* t );
  168. int _CleanUp_Queue_Call( void* h );
  169. }
  170. #endif /* _weakpointer_h_ */