RE: Type of newForeignPtr & addForeignPtrFinalizer

[ sorry for the delay in replying to this one, I'm just trying to clear some of my backlog... ]
I have a feeling this may be a stupid question, but why are the types of these.. newForeignPtr :: Ptr a -> IO () -> IO (ForeignPtr a) addForeignPtrFinalizer :: ForeignPtr a -> IO () -> IO () (second arg being the finalizer)
Won't a finaliser almost always take a pointer to the thing being finalised as an argument? If so it would be more convienient to have newForeignPtr.. newForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a) or maybe.. newForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO (ForeignPtr a)
I think the reason was simplicity - I seem to recall we originally had the versions you suggested, but realised that it isn't *necessary* for the finalizer to take a Ptr as an argument. Anyway, there's an ongoing discussion on the FFI list about whether having arbitrary Haskell finalizers is really a plausible design, so it may be that the point is moot anyway.
The first of these is easy to implement yourself I suppose.. myNewForeignPtr :: Ptr a -> (Ptr a -> IO ()) -> IO (ForeignPtr a) myNewForeignPtr p fin = newForeignPtr p (fin p)
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)) Cheers, Simon

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. Regards -- Adrian Hey

[This question might be more appropriate for the ffi mailing list]
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? [...]
The reason for using ForeignPtr is to attach free functions. If we were to make Ptr and ForeignPtr the same type, there's be no way to catch cases where we forget to attach a free function to a Ptr being returned from C. The type distinction (and the fact that ForeignPtr's must be cast to/from Ptrs when they are passed to C) acts as a strong reminder to do the right thing. -- Alastair
participants (3)
-
Adrian Hey
-
Alastair Reid
-
Simon Marlow