[Haskell-cafe] FFI woes!
robdockins at fastmail.fm
Thu Dec 16 11:08:13 EST 2004
Sebastian Sylvan wrote:
> On Thu, 16 Dec 2004 08:56:15 -0500, Robert Dockins
> <robdockins at fastmail.fm> wrote:
>>Return the high level value to the user; when the enclosed
>>ForeignPtr is garbage collected deRefWeak on the weak pointer will
>>return Nothing. Then the clean-up thread can begin polling the song
>>object to see if it is finished.
> But if the ForeignPtr has been garbage collected, it's too late! The
> sound data is *gone* and the channel can no longer play the sound.
If you look closely at the code I posted, I do something tricky; I form
a ForeignPtr (without a finalizer) from a Ptr, and then _keep them
both_. So, when the ForeignPtr is GCed, I still have the original
pointer. I detect the fact that the ForeignPtr is GCed by using a weak
pointer. Because of the way I set up my code, I know that when the
ForeignPtr is gone, my clean-up thread is the only place that I have a
pointer to the original C object. So then I start polling the sound
object to see if it is done playing, and only then free the C object.
> -- play a sample
> samplePlay :: SoundSample -> IO SamplePlayback
> samplePlay sample = do ch <- withForeignPtr sample (fsound_PlaySound (-1))
> let spb = SP ch sample -- SamplePlaybackRaw
> mkWeakPtr spb (Just (samplePlaybackFinalizer spb))
Ahh... look. You are returning a weak pointer! Those specifically
allow the referenced object to be garbage collected. So the only
references left to your SamplePlaybackRaw are (a) inside a weak pointer
and (b) inside a finalizer closure. Such references are NOT considered
reachable from the root set, and can thus be GCed (I am about 90% sure
this is true about finalizers). You have arranged it so that the RTS
can garbage collect spb, and thus the ch and sample, whenever it likes.
More information about the Haskell-Cafe