[Haskell-cafe] FFI woes!

Sebastian Sylvan sebastian.sylvan at gmail.com
Thu Dec 16 10:39:47 EST 2004

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. I
need to catch it just before the *channel* gets garbage collected and
extract the vital information from the channel so that I can keep them
alive long enough to finish playback. One of the vital pieces of
information is a reference to the sound data and the other is the
physical channel (CInt). Using those two pieces of information I
*should* be able to poll the channel to see if it is playing, and also
keep the sound data alive (touchForeignPtr). Once the channel has
finished playing I just need to return and let the GC take care of the
sound data (which may or may not have additional references from other
channels), since ITS finalizer properly releases its resources.

However this doesn't work. Strangely 

I do this (see other post for additional code)

main = do hSetBuffering stdout NoBuffering
          x <- fsound_Init 44100 32 0
          c <- callStuff
          threadDelay 1000000
          putStrLn "Performing GC!"
          threadDelay 1000000
          b <- isPlaying c
          print b
          return ()

callStuff = do s <- sampleLoad "test.mp3"
               c <- samplePlay s
               threadDelay 3000000
               b <- isPlaying c              
               print b
               threadDelay 1000000
               return c

And expect to get output along the lines of:

Performing GC
Starting keep-alive loop for sample playback
Keeping channel alive!
Keeping channel alive!
Keeping channel alive!
Keeping channel alive!
Finished keeping sample alive
Freeing up sample!

Instead I get:
Performing GC!
Freeing up sample
Starting keep-alive loop for sample playback
Keeping channel alive!
Finished keeping sample alive

In other words after the GC the first thing that happens is that the
_sound_data_ is being garbage collected! That's extremly freaky since
the channel (which is used later on to produce the "False" value from
isPlaying) contains a reference to this sound data!
THEN the keep-alive loop starts (and since isPlaying naturally returns
False since there is no sound data anymore, it immediatly returns).

I don't understand this behaviour.


Sebastian Sylvan
UIN: 44640862

More information about the Haskell-Cafe mailing list