> Yes, that's right. It is often the case that there *is* no shared
> state so a Haskell finalizer is fine. But if there is, then there
> has to be some mechanism for atomic operations. C is one such
> mechanism.
I claim that the major thing that finalizers do is manipulate shared
state. Their task is to clean up when an object dies and the reason
we care whether or not that cleanup happens is that the thing being
cleaned is shared with live objects/threads.
If I want to manipulate shared C state, then finalizers written in C
do rather well. I see no compelling need to write them in Haskell.
(And I see significant problems in encouraging people to write them in
Haskell.)
To get any benefit from writing finalizers in Haskell, I have to have
MVars which protect against finalizers. Malcolm: are you ready to add
MVars to NHC?
> But there's something I'm puzzled about. Hugs does support
> non-pre-emptive concurrency, right? (Where can I find a description
> of it.)
I don't think I ever described it in print.
Mark Jones implemented the IO monad using two continuations:
an error continuation: IOError -> ()
and a success continuation: a -> ()
On this base, I added MVars (whose state is either a value or a list
of success continuations) and a queue of running tasks. Context
switches happen when you manipulate MVars and when a thread
terminates.
> So would it not be easy to implement (non-pre-emptive) MVars?
Yes, we have those.
Of course, NHC will have to add them too. There's no reasonable way
to add Haskell finalizers without providing locking as well.
> And if they existed, everything would be fine, right? We could
> just use Haskell finalizers as we all want. Or am I missing
> something.
Finalizers would have to be scheduled by the same scheduler as normal
threads. (This is the key change. SimonM's patch effectively set up
the garbage collector as a separate scheduler much as 'scheduling' of
CPU interrupts isn't handled by the pthread scheduler.)
The scheduler would need to prioritize finalizers over normal threads.
That is finalizers should be run whenever they are runnable. This is
essential in cooperative schedulers because you never know when or if
a thread will give up control.
Most of the cooperative concurrency implementation is written in
Haskell. That would have to be rewritten in C to make the operations
atomic wrt garbage collection.
I think there's a bunch of other changes needed but it's way past my
bedtime - I'll need to think more about this.
> (I'm assuming that the starting point for the entire discussion is
> whether finalizers are written in Haskell or C. Please let me know
> if I missed something.)
That's pretty much it.
Of course, to get any benefit from restricting them to being written
in C, C finalizers have to be restricted to not call Haskell code.
(Calling the Haskell runtime isn't ruled out though some calls like
performGC may be off limits.)
And to get any benefit from allowing finalizers to be written in
Haskell, you have to have MVars.
--
Alastair