Back to index

lightning-sunbird  0.9+nobinonly
weakpointer.h
Go to the documentation of this file.
00001 #ifndef       _weakpointer_h_
00002 #define       _weakpointer_h_
00003 
00004 /****************************************************************************
00005 
00006 WeakPointer and CleanUp
00007 
00008     Copyright (c) 1991 by Xerox Corporation.  All rights reserved.
00009 
00010     THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00011     OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00012 
00013     Permission is hereby granted to copy this code for any purpose,
00014     provided the above notices are retained on all copies.
00015 
00016     Last modified on Mon Jul 17 18:16:01 PDT 1995 by ellis
00017 
00018 ****************************************************************************/
00019 
00020 /****************************************************************************
00021 
00022 WeakPointer
00023 
00024 A weak pointer is a pointer to a heap-allocated object that doesn't
00025 prevent the object from being garbage collected. Weak pointers can be
00026 used to track which objects haven't yet been reclaimed by the
00027 collector. A weak pointer is deactivated when the collector discovers
00028 its referent object is unreachable by normal pointers (reachability
00029 and deactivation are defined more precisely below). A deactivated weak
00030 pointer remains deactivated forever.
00031 
00032 ****************************************************************************/
00033 
00034 
00035 template< class T > class WeakPointer {
00036 public:
00037 
00038 WeakPointer( T* t = 0 )
00039     /* Constructs a weak pointer for *t. t may be null. It is an error
00040        if t is non-null and *t is not a collected object. */
00041     {impl = _WeakPointer_New( t );}
00042 
00043 T* Pointer()
00044     /* wp.Pointer() returns a pointer to the referent object of wp or
00045        null if wp has been deactivated (because its referent object
00046        has been discovered unreachable by the collector). */
00047     {return (T*) _WeakPointer_Pointer( this->impl );}
00048 
00049 int operator==( WeakPointer< T > wp2 )
00050     /* Given weak pointers wp1 and wp2, if wp1 == wp2, then wp1 and
00051        wp2 refer to the same object. If wp1 != wp2, then either wp1
00052        and wp2 don't refer to the same object, or if they do, one or
00053        both of them has been deactivated. (Note: If objects t1 and t2
00054        are never made reachable by their clean-up functions, then
00055        WeakPointer<T>(t1) == WeakPointer<T>(t2) if and only t1 == t2.) */
00056     {return _WeakPointer_Equal( this->impl, wp2.impl );}
00057 
00058 int Hash()
00059     /* Returns a hash code suitable for use by multiplicative- and
00060        division-based hash tables. If wp1 == wp2, then wp1.Hash() ==
00061        wp2.Hash(). */
00062     {return _WeakPointer_Hash( this->impl );}
00063 
00064 private:
00065 void* impl;
00066 };
00067 
00068 /*****************************************************************************
00069 
00070 CleanUp
00071 
00072 A garbage-collected object can have an associated clean-up function
00073 that will be invoked some time after the collector discovers the
00074 object is unreachable via normal pointers. Clean-up functions can be
00075 used to release resources such as open-file handles or window handles
00076 when their containing objects become unreachable.  If a C++ object has
00077 a non-empty explicit destructor (i.e. it contains programmer-written
00078 code), the destructor will be automatically registered as the object's
00079 initial clean-up function.
00080 
00081 There is no guarantee that the collector will detect every unreachable
00082 object (though it will find almost all of them). Clients should not
00083 rely on clean-up to cause some action to occur immediately -- clean-up
00084 is only a mechanism for improving resource usage.
00085 
00086 Every object with a clean-up function also has a clean-up queue. When
00087 the collector finds the object is unreachable, it enqueues it on its
00088 queue. The clean-up function is applied when the object is removed
00089 from the queue. By default, objects are enqueued on the garbage
00090 collector's queue, and the collector removes all objects from its
00091 queue after each collection. If a client supplies another queue for
00092 objects, it is his responsibility to remove objects (and cause their
00093 functions to be called) by polling it periodically.
00094 
00095 Clean-up queues allow clean-up functions accessing global data to
00096 synchronize with the main program. Garbage collection can occur at any
00097 time, and clean-ups invoked by the collector might access data in an
00098 inconsistent state. A client can control this by defining an explicit
00099 queue for objects and polling it at safe points.
00100 
00101 The following definitions are used by the specification below:
00102 
00103 Given a pointer t to a collected object, the base object BO(t) is the
00104 value returned by new when it created the object. (Because of multiple
00105 inheritance, t and BO(t) may not be the same address.)
00106 
00107 A weak pointer wp references an object *t if BO(wp.Pointer()) ==
00108 BO(t).
00109 
00110 ***************************************************************************/
00111 
00112 template< class T, class Data > class CleanUp {
00113 public:
00114 
00115 static void Set( T* t, void c( Data* d, T* t ), Data* d = 0 )
00116     /* Sets the clean-up function of object BO(t) to be <c, d>,
00117        replacing any previously defined clean-up function for BO(t); c
00118        and d can be null, but t cannot. Sets the clean-up queue for
00119        BO(t) to be the collector's queue. When t is removed from its
00120        clean-up queue, its clean-up will be applied by calling c(d,
00121        t). It is an error if *t is not a collected object. */ 
00122        {_CleanUp_Set( t, c, d );}
00123 
00124 static void Call( T* t )
00125     /* Sets the new clean-up function for BO(t) to be null and, if the
00126        old one is non-null, calls it immediately, even if BO(t) is
00127        still reachable. Deactivates any weak pointers to BO(t). */
00128        {_CleanUp_Call( t );}
00129 
00130 class Queue {public:
00131     Queue()
00132         /* Constructs a new queue. */
00133             {this->head = _CleanUp_Queue_NewHead();}
00134 
00135     void Set( T* t )
00136         /* q.Set(t) sets the clean-up queue of BO(t) to be q. */
00137             {_CleanUp_Queue_Set( this->head, t );}
00138 
00139     int Call()
00140         /* If q is non-empty, q.Call() removes the first object and
00141            calls its clean-up function; does nothing if q is
00142            empty. Returns true if there are more objects in the
00143            queue. */
00144            {return _CleanUp_Queue_Call( this->head );}
00145 
00146     private:
00147     void* head;
00148     };
00149 };
00150 
00151 /**********************************************************************
00152 
00153 Reachability and Clean-up
00154 
00155 An object O is reachable if it can be reached via a non-empty path of
00156 normal pointers from the registers, stacks, global variables, or an
00157 object with a non-null clean-up function (including O itself),
00158 ignoring pointers from an object to itself.
00159 
00160 This definition of reachability ensures that if object B is accessible
00161 from object A (and not vice versa) and if both A and B have clean-up
00162 functions, then A will always be cleaned up before B. Note that as
00163 long as an object with a clean-up function is contained in a cycle of
00164 pointers, it will always be reachable and will never be cleaned up or
00165 collected.
00166 
00167 When the collector finds an unreachable object with a null clean-up
00168 function, it atomically deactivates all weak pointers referencing the
00169 object and recycles its storage. If object B is accessible from object
00170 A via a path of normal pointers, A will be discovered unreachable no
00171 later than B, and a weak pointer to A will be deactivated no later
00172 than a weak pointer to B.
00173 
00174 When the collector finds an unreachable object with a non-null
00175 clean-up function, the collector atomically deactivates all weak
00176 pointers referencing the object, redefines its clean-up function to be
00177 null, and enqueues it on its clean-up queue. The object then becomes
00178 reachable again and remains reachable at least until its clean-up
00179 function executes.
00180 
00181 The clean-up function is assured that its argument is the only
00182 accessible pointer to the object. Nothing prevents the function from
00183 redefining the object's clean-up function or making the object
00184 reachable again (for example, by storing the pointer in a global
00185 variable).
00186 
00187 If the clean-up function does not make its object reachable again and
00188 does not redefine its clean-up function, then the object will be
00189 collected by a subsequent collection (because the object remains
00190 unreachable and now has a null clean-up function). If the clean-up
00191 function does make its object reachable again and a clean-up function
00192 is subsequently redefined for the object, then the new clean-up
00193 function will be invoked the next time the collector finds the object
00194 unreachable.
00195 
00196 Note that a destructor for a collected object cannot safely redefine a
00197 clean-up function for its object, since after the destructor executes,
00198 the object has been destroyed into "raw memory". (In most
00199 implementations, destroying an object mutates its vtbl.)
00200 
00201 Finally, note that calling delete t on a collected object first
00202 deactivates any weak pointers to t and then invokes its clean-up
00203 function (destructor).
00204 
00205 **********************************************************************/
00206 
00207 extern "C" {
00208     void* _WeakPointer_New( void* t );
00209     void* _WeakPointer_Pointer( void* wp );
00210     int _WeakPointer_Equal( void* wp1, void* wp2 );
00211     int _WeakPointer_Hash( void* wp );
00212     void _CleanUp_Set( void* t, void (*c)( void* d, void* t ), void* d );
00213     void _CleanUp_Call( void* t );
00214     void* _CleanUp_Queue_NewHead ();
00215     void _CleanUp_Queue_Set( void* h, void* t );
00216     int _CleanUp_Queue_Call( void* h );
00217 }
00218 
00219 #endif /* _weakpointer_h_ */
00220 
00221