# On why we have `ForeignPtr`

Unfortunately it isn't possible to add a finalizer to a normal `Ptr a`. We already have a generic finalization mechanism: see the Weak module in package lang. But the only reliable way to use finalizers is to attach one to an atomic heap object - that way the compiler's optimiser can't interfere with the lifetime of the object.

The `Ptr` type is really just a boxed address - it's defined like

    data Ptr a = Ptr Addr#

where `Addr#` is an unboxed native address (just a 32- or 64- bit word). Putting a finalizer on a `Ptr` is dangerous, because the compiler's optimiser might remove the box altogether.

`ForeignPtr` is defined like this

    data ForeignPtr a = ForeignPtr ForeignObj#

where `ForeignObj#` is a *boxed* address, it corresponds to a real heap object. The heap object is primitive from the point of view of the compiler - it can't be optimised away. So it works to attach a finalizer to the `ForeignObj#` (but not to the `ForeignPtr`!).

There are several primitive objects to which we can attach finalizers: `MVar#`, `MutVar#`, `ByteArray#`, etc. We have special functions for some of these: eg. `MVar.addMVarFinalizer`.

So a nicer interface might be something like

    class Finalizable a where
       addFinalizer :: a -> IO () -> IO ()

    instance Finalizable (ForeignPtr a) where ...
    instance Finalizable (MVar a) where ...

So you might ask why we don't just get rid of `Ptr` and rename `ForeignPtr` to `Ptr`. The reason for that is just efficiency, I think.

Last modified: Wed Sep 26 09:49:37 BST 2001