[Gc] [boehms-gc] Extend Boehm's GC disappearing link facility withcallbacks-on-disappear

Boehm, Hans hans.boehm at hp.com
Mon Aug 14 11:35:21 PDT 2006


Isn't this implementable with finalization?

There is also a long-standing request, posted on the GC list quite a
while ago, by Petter Urkedal I think, to provide a more general callback
mechanism to allow the client to implement custom weak-pointer like
things.  He included some largish patches, which unfortunately I've
never gotten around to massaging a bit and putting into the tree.  I
think that something along those lines, that essentially allows the user
to keep a list of "custom" weak pointers, would be a better direction. 

Callback procedures from inside the collector are generally tricky.
Deadlock possibilities and the like abound.  I think it's worth devoting
some effort to documenting exactly what the callbacks can and cannot do.
They clearly cannot allocate memory.  That means they cannot acquire
Java locks.  They probably should not generally acquire other locks,
since threads holding those locks may be blocked on allocation.

Lastly, note that all of this stuff, along with finalization in general,
is on thin ice, in that objects can generally disappear before
programmers think they should, e.g. while a C++ member function of the
object is still running and accessing the data that you are about to
clean up.  For some details on the Java version of the problem see
http://www.hpl.hp.com/personal/Hans_Boehm/misc_slides/java_finalizers.pd
f .

Hans

> -----Original Message-----
> From: gc-bounces at napali.hpl.hp.com 
> [mailto:gc-bounces at napali.hpl.hp.com] On Behalf Of Laurynas Biveinis
> Sent: Friday, August 11, 2006 5:12 AM
> To: Gcc Patch List; gc at napali.hpl.hp.com
> Cc: Daniel Berlin
> Subject: [Gc] [boehms-gc] Extend Boehm's GC disappearing link 
> facility withcallbacks-on-disappear
> 
> Hi,
> 
> Boehm's GC has weak pointer support, but sometimes setting 
> the weak pointer to NULL when the object pointed by it 
> disappears, is not what is required for the application, for 
> example GCC hash tables use non-NULL values for deleted entries.
> 
> To achieve the desired behaviour I've added a very simple 
> implementation to register callback which is called on the 
> disappearing link and may execute arbitrary actions on it.
> 
> How do collector folks view this idea? Is this desirable to 
> have in mainstream collector sources? At this point there are 
> following design/implementation issues:
> 1) What is desired behaviour in the case when disappearing 
> link is registered twice - with the same link, the same 
> object, but different callback?
> 2) I didn't test K&R prototype part at all.
> 3) The price for this support is that struct 
> disappearing_link is increased by size of two pointers. I 
> hope that's acceptable.
> 4) I think API should have a new function to unregister all 
> the disappearing links at once (compare to GC_clear_roots). 
> My GCC changes already could use that.
> 4) Naming conventions/coding style/documentation is shaky at 
> best for now.
> 
> The patch is against 6.8 GCC local copy. Commited to the 
> boehms-gc branch. The GCC changes that use this patch come in 
> separate mail.
> 
> Index: boehm-gc/include/gc.h
> ===================================================================
> --- boehm-gc/include/gc.h	(revision 115922)
> +++ boehm-gc/include/gc.h	(working copy)
> @@ -760,6 +760,13 @@
>  	/* the object containing link.  Explicitly deallocating */
>  	/* obj may or may not cause link to eventually be	*/
>  	/* cleared.						*/
> +typedef void (*GC_disappearing_link_callback_proc)
> +       GC_PROTO((GC_PTR * dissapearing_link, GC_PTR obj, 
> GC_PTR info));
> +
> +GC_API int GC_general_register_disappearing_link_callback
> +       GC_PROTO((GC_PTR * /* link */, GC_PTR obj,
> +		 GC_disappearing_link_callback_proc callback, 
> GC_PTR info));
> +
>  GC_API int GC_unregister_disappearing_link GC_PROTO((GC_PTR 
> * /* link */));
>  	/* Returns 0 if link was not actually registered.	*/
>  	/* Undoes a registration by either of the above two	*/
> Index: boehm-gc/finalize.c
> ===================================================================
> --- boehm-gc/finalize.c	(revision 115762)
> +++ boehm-gc/finalize.c	(working copy)
> @@ -31,7 +31,7 @@
>  /* Type of mark procedure used for marking from finalizable 
> object.	*/
>  /* This procedure normally does not mark the object, only 
> its		*/
>  /* descendents.						
> 		*/
> -typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
> +typedef void finalization_mark_proc(/* ptr_t finalizable_obj_ptr */);
> 
>  # define HASH3(addr,size,log_size) \
>      ((((word)(addr) >> 3) ^ ((word)(addr) >> 
> (3+(log_size)))) \ @@ -54,6 +54,11 @@
>  #   define dl_set_next(x,y) (x) -> prolog.next = (struct 
> hash_chain_entry *)(y)
> 
>      word dl_hidden_obj;		/* Pointer to object 
> base	*/
> +                                /* What to do with the link 
> when object
> +				   disappears. If callback is 
> NULL, will just
> +				   set the link to NULL. */
> +    GC_disappearing_link_callback_proc callback_on_disappear;
> +    word dl_hidden_info; /* Arbitrary information for the callback */
>  } **dl_head = 0;
> 
>  static signed_word log_dl_table_size = -1; @@ -160,6 +165,22 
> @@  # endif
> 
>  {
> +  return(GC_general_register_disappearing_link_callback(link, obj,
> NULL, NULL));
> +}
> +
> +# if defined(__STDC__) || defined(__cplusplus)
> +    int GC_general_register_disappearing_link_callback(GC_PTR * link,
> +						       GC_PTR obj,
> +						       
> GC_disappearing_link_callback_proc callback,
> +						       GC_PTR info)
> +# else
> +      int 
> GC_general_register_disappearing_link_callback(link, obj, callback)
> +      GC_PTR * link;
> +      GC_PTR   obj;
> +      GC_disappearing_link_callback_proc callback;
> +      GC_PTR   info;
> +# endif
> +{
>      struct disappearing_link *curr_dl;
>      int index;
>      struct disappearing_link * new_dl;
> @@ -221,6 +242,8 @@
>      }
>      new_dl -> dl_hidden_obj = HIDE_POINTER(obj);
>      new_dl -> dl_hidden_link = HIDE_POINTER(link);
> +    new_dl -> callback_on_disappear = callback;
> +    new_dl -> dl_hidden_info = HIDE_POINTER(info);
>      dl_set_next(new_dl, dl_head[index]);
>      dl_head[index] = new_dl;
>      GC_dl_entries++;
> @@ -228,7 +251,7 @@
>          UNLOCK();
>          ENABLE_SIGNALS();
>  #   endif
> -    return(0);
> +  return 0;
>  }
> 
>  # if defined(__STDC__) || defined(__cplusplus) @@ -516,7 +539,7 @@  {
>      struct disappearing_link * curr_dl;
>      struct finalizable_object * curr_fo;
> -    ptr_t real_ptr, real_link;
> +    ptr_t real_ptr, real_link, callback_proc, real_info;
>      int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << 
> log_dl_table_size);
>      int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << 
> log_fo_table_size);
>      int i;
> @@ -526,7 +549,10 @@
>        for (curr_dl = dl_head[i]; curr_dl != 0; curr_dl = 
> dl_next(curr_dl)) {
>          real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
>          real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
> -        GC_printf2("Object: 0x%lx, Link:0x%lx\n", real_ptr, 
> real_link);
> +	callback_proc = (ptr_t)(curr_dl -> callback_on_disappear);
> +	real_info = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_info);
> +        GC_printf4("Object: 0x%lx, Link:0x%lx, 
> Callback:0x%lx, Info:0x%lx\n",
> +		   real_ptr, real_link, callback_proc, real_info);
>        }
>      }
>      GC_printf0("Finalizers:\n");
> @@ -545,11 +571,12 @@
>  {
>      struct disappearing_link * curr_dl, * prev_dl, * next_dl;
>      struct finalizable_object * curr_fo, * prev_fo, * next_fo;
> -    ptr_t real_ptr, real_link;
> +    ptr_t real_ptr, real_link, real_info;
> +    GC_disappearing_link_callback_proc callback_proc;
>      register int i;
>      int dl_size = (log_dl_table_size == -1 ) ? 0 : (1 << 
> log_dl_table_size);
>      int fo_size = (log_fo_table_size == -1 ) ? 0 : (1 << 
> log_fo_table_size);
> -
> +
>    /* Make disappearing links disappear */
>      for (i = 0; i < dl_size; i++) {
>        curr_dl = dl_head[i];
> @@ -557,8 +584,13 @@
>        while (curr_dl != 0) {
>          real_ptr = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_obj);
>          real_link = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_link);
> +	real_info = (ptr_t)REVEAL_POINTER(curr_dl -> dl_hidden_info);
> +	callback_proc = curr_dl -> callback_on_disappear;
>          if (!GC_is_marked(real_ptr)) {
> -            *(word *)real_link = 0;
> +	    if (callback_proc == NULL)
> +                *(word *)real_link = 0;
> +	    else
> +	        (*callback_proc)((GC_PTR)real_link, real_ptr, 
> real_info);
>              next_dl = dl_next(curr_dl);
>              if (prev_dl == 0) {
>                  dl_head[i] = next_dl;
> 
> 
> --
> Laurynas
> _______________________________________________
> Gc mailing list
> Gc at linux.hpl.hp.com
> http://www.hpl.hp.com/hosted/linux/mail-archives/gc/
> 



More information about the Gc mailing list