George Russell <ger at tzi.de> writes:
> Unfortunately some sort of cascade is exactly what we want and need when
> the Haskell finaliser indicates that Haskell is no longer interested in
> some Foogle object, which means Foogle can run a GC which indicates
> Foogle is no longer interested in some Haskell object and so on . . .
Yes. The key thing is just to delay the steps of the cascade so
that you are not trying to call Haskell/Foogle code whilst there is
no Haskell/Foogle heap available to run it.
> > After that, it doesn't matter when the Foogle finaliser decides to run.
>> But surely Foogle has no way of knowing when the Haskell GC is over?
When sequential control returns to the Foogle world, that is when
the Haskell GC is guaranteed to be complete.
> Suppose Haskell does
>> [enter GC]
> ...
> [run finaliser 1]
> ...
> [run finaliser 2]
> ...
> [leave GC]
>> Then you want Foogle to delay any Haskell calls consequent on finaliser
> 1 until [leave GC], don't you? How can it?
Because the Haskell calls don't happen until the Foogle GC invokes them.
Ok, you have a Haskell ForeignPtr which is really a Foogle object.
It becomes garbage. At the next Haskell GC, its finaliser is run.
The finaliser is not Haskell code. The finaliser is Foogle code.
This finaliser runs and a Haskell StablePtr contained within the
Foogle object becomes garbage. Although the Haskell object is
regarded as a StablePtr in Haskell land, it is a Foogle ForeignPtr.
Hence, its finaliser does not run yet. The Haskell GC finishes.
Computation proceeds. At some later moment, Foogle exhausts its heap
and starts a GC. The finaliser for the garbage object is now run.
This is not Foogle code, it is Haskell code. In fact, it is the Haskell
routine freeStablePtr. This is ok, because we have sufficient heap to
run the finaliser. The StablePtr is released. The Foogle GC finishes.
Computation proceeds.
> Is it really so difficult to create some queue of delayed functions
> which can be appended to from C and which nhc checks every time it does
> "leave GC"?
I did implement this, once. The problem is that we don't know when to
run the delayed finaliser. The moment Haskell GC finishes is *not*
a good time. Some arbitrary reduction step is in mid-progress,
and running another process at this moment corrupts the context.
What you really need is some kind of scheduler that can decide when
it is safe to run an independent thread.
Regards,
Malcolm