[MLton] adding synchronous finalizers
Stephen Weeks
MLton@mlton.org
Wed, 29 Sep 2004 17:07:07 -0700
> The idea of a single-threaded program manually clearing out finalizers sounds
> good, but do we really want this to be a run-time or a compile-time decision.
> Perhaps I am thinking too much about the optimizations we lose when multiple
> threads exist, but I would think that the distinction between multi-threaded
> and single-threaded is almost certainly going to be known at compile time.
> Hence it should be set by a compile-time flag.
I agree that it will usually be known at compile time. But I'm not
sure that it always will, so it seems more flexible to make it a bool
ref. It's also a bit easier (although not so bad now that we have
nice support for compile-time constants).
As to the performance, I think the implementation can be set up so
that if one wants synchronous finalizers, then the GC signal handler
won't even be used. But I'm not sure if it's possible to go the extra
step of convincing MLton's dead-code pass to eliminate all the thread
stuff. And I'm not sure it's worth the effort -- perhaps we should
spend more effort smoothing out the performance dropoff of programs
that use threads or finalizers (actually, I'm not really sure it's
that big of a dropoff these days, but it might be).
> Speaking of finalizers, I would think that the exact same arguments would
> apply to signals.
>
> I.e., what we really want is a flag (indicating now signal checking nor
> finalization running automatically) and a single function, something link
> MLton.poll of type unit -> unit which runs any finalizers waiting and also
> handles any pending signals.
Makes sense, in principle. The problem is that we expose a more
complicated interface to normal signal handlers than we do to the GC
signal handler. Normal signal handlers are of type
MLton.Thread.Runnable.t -> MLton.Thread.Runnable.t
while all we expose about the GC signal is the MLton.Finalizable
interface, which includes
val addFinalizer: 'a t * ('a -> unit) -> unit
Hence, it's quite easy to understand what it means to run the
finalizers synchronously -- apply each finalizer to the appropriate
value and continue with the main thread.
For normal signal handlers, their semantics allows them to change
threads by returning a thread other than the one they are passed. How
should we package that into a poll function?