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