ForeignPtr representation

David Feuer david.feuer at
Tue Sep 4 23:22:55 UTC 2018

I'm trying, and failing, to understand why ForeignPtr is defined the way it
is. It all seems rather complicated and redundant. I was thinking we might
want to switch to something simpler and more explicit, like this:

data ForeignPtr a = ForeignPtr {
  fptr :: !(Ptr a) -- What we point to
  froot :: MutableByteArray# RealWorld
  fwk :: MutVar# RealWorld Any -- The finalizers

froot represents the object the ForeignPtr points into. When created by one
of the malloc variants, this will actually be the allocated byte array.
Otherwise, it will be a 0-length array.

fwk should be seen as having type

  fwk :: MutVar# RealWorld (Weak# (MutableByteArray# RealWorld))

but we can't express that directly right now. fwk is keyed on froot, and in
the malloc case also points to it, to prevent it from being freed

It seems that this representation requires a couple extra primitive
features from Weak#. I think that's okay: Weak# already has some primitive
features designed to support ForeignPtr.

1. An operation to add a Haskell finalizer to a Weak#, similar to the one
that adds a C finalizer.

2. A way to deal with mixed finalizers: either make the finalizer-adding
primops report distinguishable failure on mixing or arrange to run the C
finalizers after any Haskell finalizers (since C finalizers are much more
likely to actually invalidate the pointer).

3. A documented guarantee about the order in which the finalizers attached
to a particular Weak# run, compatible with the ForeignPtr documentation.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the ghc-devs mailing list