
-- 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))
From the System.Mem.Weak docs for addFinalizer: Note: adding a finalizer to a ForeignPtr using addFinalizer won't work as well as using the specialised version addForeignPtrFinalizer because the latter version adds the finalizer to the primitive ForeignPtr# object inside, whereas the generic addFinalizer will add the finalizer to the box. Optimisations tend to remove the box, which may cause the finalizer to run earlier than you intended. The same motivation justifies the existence of addMVarFinalizer and mkWeakIORef (the non-unformity is accidental). This note also applies to the use of mkWeakPtr. So if you want to protect the raw pointer, using weak pointer finalizers is not the way to go, because of the problem with optimizations. If you are going to use finalizers, you should use the ForeignPtr versions (that's the main reason why ForeignPtr exists). The usage I suggested only used weak pointers to detect the fact that the foreign pointer had been garbage collected, and did not use finalizers at all.