<div dir="auto">I realized that the current representation is kind of balanced on a knife edge, efficiency-wise. There's probably no way to make one thing faster without slowing down another: there are just too many things a ForeignPtr could be trying to represent.</div><br><div class="gmail_quote"><div dir="ltr">On Thu, Sep 6, 2018, 3:15 AM Simon Marlow <<a href="mailto:marlowsd@gmail.com">marlowsd@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>Wouldn't this mean that unpacking a ForeignPtr is one word longer than it is now? That would have a big impact on ByteString.</div><div><br></div><div>What do you think is redundant in the current representation?</div><div><br></div><div>Cheers</div><div>Simon<br></div></div><br><div class="gmail_quote"><div dir="ltr">On Wed, 5 Sep 2018 at 00:23, David Feuer <<a href="mailto:david.feuer@gmail.com" target="_blank" rel="noreferrer">david.feuer@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">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:<div dir="auto"><br></div><div dir="auto">data ForeignPtr a = ForeignPtr {</div><div dir="auto"> fptr :: !(Ptr a) -- What we point to</div><div dir="auto"> froot :: MutableByteArray# RealWorld</div><div dir="auto"> fwk :: MutVar# RealWorld Any -- The finalizers</div><div dir="auto"> }</div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto">fwk should be seen as having type</div><div dir="auto"><br></div><div dir="auto"> fwk :: MutVar# RealWorld (Weak# (MutableByteArray# RealWorld))</div><div dir="auto"><br></div><div dir="auto">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 prematurely.</div><div dir="auto"><br></div><div dir="auto">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.</div><div dir="auto"><br></div><div dir="auto">1. An operation to add a Haskell finalizer to a Weak#, similar to the one that adds a C finalizer.</div><div dir="auto"><br></div><div dir="auto">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).</div><div dir="auto"><br></div><div dir="auto">3. A documented guarantee about the order in which the finalizers attached to a particular Weak# run, compatible with the ForeignPtr documentation.</div></div>
</blockquote></div>
</blockquote></div>