Sebastian Sylvan wrote:

On Thu, 16 Dec 2004 08:56:15 -0500, Robert Dockins
<[EMAIL PROTECTED]> 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.



_______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to