RE: Type of newForeignPtr & addForeignPtrFinalizer

On Monday 22 July 2002 12:33 pm, Simon Marlow wrote:
The second seems to require this bit of weirdness.. myNewForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a) myNewForeignPtr p fin = do newfp <- newForeignPtr p (return ()) addForeignPtrFinalizer newfp (fin newfp) return newfp
You can do this more easily using fixIO:
myNewForeignPtr p fin = do fixIO (\fp -> newForeignPtr p (fin fp))
Thanks, neat (I think:-). I wonder if I might indulge myself with another stupid question related to this, that is, why make the distinction between Ptr and ForeignPtr at all?
By definition a ForeignPtr has a non-zero number of finalisers and Ptr has no finalisers. Couldn't you just allow ForeignPtr's to have no finalisers and dispense with Ptr alltogether? Then you could just add finalisers as required rather than converting between types. It seems that when making a foreign binding you have to make what seems (to me) an arbitrary choice between Ptr and ForeignPtr arguments. I don't really understand the reason for this extra complexity.
There's a difference in representation between Ptr & ForeignPtr, which means that ForeignPtr might be significantly less efficient than Ptr. ForeignPtr is represented as (ForeignPtr ForeignPtr#), where ForeignPtr# is a real heap object of size 2. It needs to be a heap object so that the garbage collector can keep track of it and tell when it needs to be finalized. Ptr on the other hand is represented as (Ptr Addr#) where Addr# is just an unboxed address - it doesn't live on the heap, so the garbage collector can't track it. You might ask why we can't just put the finalizer on the boxed version (the (Ptr Addr#)) - and the answer is that the compiler might optimise away the box, which might cause the finalizer to run earlier than you intended. The compiler can't optimise away the box on a ForeignPtr#, because as far as the compiler is concerned a ForeignPtr# is a primitive indivisible object. It's quite a subtle point, but an important one. My advice is to use Ptr unless you really really need ForeignPtr. There are very few guarantees about the behaviour of finalizers - about the only guarantee you've got is that the finalizer will run "eventually", so it's difficult to provide any guarantees about memory use if you rely on finalizers to free memory. Cheers, Simon
participants (1)
-
Simon Marlow