GC finalizer optimization.

Sean Kelly sean at f4.ca
Tue Apr 11 19:32:58 PDT 2006


Dave wrote:
> Dave wrote:
>>
>> Argh - I forgot about needing to release synchronization resources or 
>> zeroing the vptr. regardless of if there is a dtor or not...
>>
>> Damn.
>>
> 
> Maybe all is not lost, change gcx.setFinalizer to:
> 
>     void setFinalizer(void *p, GC_FINALIZER pFn)
>     {
>     // should be thread-safe - Threads.nthreads is
>     //  mutex'd in std/thread.d
>         if(Thread.nthreads > 1)
>         {
>         synchronized (gcLock)
>         {
>             gcx.finalizer = pFn;
>             gcx.doFinalize(p);
>         }
>         }
>         else
>         {
>             gcx.finalizer = pFn;
>             gcx.doFinalize(p);
>         }
>     }

This will optimize the code path for single-threaded programs, but I 
would advise against ever calling setFinalizer from user code.  So far 
as I can tell, the setFinalizer call is an artifact of the days before D 
classes could have dtors.  While you'd think setFinalizer sets a 
per-object finalizer pointer, it actually sets a bit flag indicating 
that p should be finalized and then sets a global pointer to the 
finalizer function.  Thus:

     gc_setFinalizer( p, null );
     gc_fullCollect();

will actually cause all orphaned objects to not be finalized during the 
collection, as the GC's finalizer pointer will be null.

I think the GC should be restructured so that setting the global 
finalizer function is available as a separate option from the function 
that indicates p should be finalized.  In fact, the finalizer should 
probably either be an established extern (C) function or set via 
gc_init, assuming it doesn't live inside the GC code.

For Ares, I've decided to make the finalizer a named C function 
(rt_finalize), and GC allocator functions now accept a parameter to 
indicate whether the block should be finalized on deletion/collection.


Sean



More information about the Digitalmars-d mailing list