Type of newForeignPtr & addForeignPtrFinalizer

Simon Marlow simonmar@microsoft.com
Mon, 22 Jul 2002 12:33:26 +0100


[ 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)
>=20
> 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=20
> (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 =3D newForeignPtr p (fin p)
>=20
> The second seems to require this bit of weirdness..
>  myNewForeignPtr :: Ptr a -> (ForeignPtr a -> IO ()) -> IO=20
> (ForeignPtr a)
>  myNewForeignPtr p fin =3D do
>    newfp  <- newForeignPtr p (return ())
>    addForeignPtrFinalizer newfp (fin newfp)
>    return newfp

You can do this more easily using fixIO:

   myNewForeignPtr p fin =3D do
	fixIO (\fp -> newForeignPtr p (fin fp))

Cheers,
	Simon