Hi Folks, I'd like to propose two new functions for the ForeignPtr interface:
I'm a bit uneasy about this.
It seems like decisions made on technological grounds (i.e., because they enable an optimization) tend to date rather quickly because the technology tends to change too.
Hmm, I see your point. Nevertheless, I think even without the tricks I'm using in GHC, the case where a ForeignPtr is used in conjunction with malloc()/free() is one which is likely to be optimisable in any system with its own memory management.
The functions may cover a fairly common case of using ForeignPtrs (though I've never used ForeignObjs or MallocPtrs that way) - but most code doesn't use ForeignPtrs so it's a common case of an uncommon thing.
Ok, I'll give some more motivation. I've been converting over some old FFI code, namely GHC's POSIX library. This was written back in the old days before the FFI, and uses lots of GHC extensions. One such extension, which doesn't have an equivalent in the FFI, is to use ByteArrays as garbage-collected chunks of memory which can be passed to foreign functions. The example I'm looking at right now is the SignalSet type in the POSIX library: a SignalSet is a pure value, and there are operations to create new empty/full sets, and create new sets by adding/deleting elements from existing sets. All these operations are pure and work outside the IO monad: emptySignalSet :: SignalSet fullSignalSet :: SignalSet addSignal :: Signal -> SignalSet -> SignalSet deleteSignal :: Signal -> SignalSet -> SignalSet inSignalSet :: Signal -> SignalSet -> Bool However, inside a SignalSet is a real sigset_t which can be passed to the C functions which operate on it. An ideal opportunity for a ForeignPtr, one might think: but using a ForeignPtr here, with free() as its finalizer, adds so much overhead that it would be better to go back to manipulating SignalSets in the IO monad (perhaps this isn't such a good example, it's unlikely that someone is going to be doing a lot of SignalSet mangling, but anyway). Another possibility is to fully marshal the sigset_t into Haskell. The marshalling would be quite expensive, but if there was a lot of manipulation of the SignalSet going on in Haskell land then this might be a good choice. This is a well-known tradeoff; and sometimes it isn't possible to do the marshalling because the C type is abstract. The main point is that having a cheap way to use ForeignPtr with malloc()/free() makes it much more likely that we'll settle on a nice pure interface in this case, because the overhead for doing so is significantly lower.
I'm inclined to say: add it to GHC for now and prod us again once a decent body of examples builds up.
Well, I'll do this if I have to, but I don't really want to make my FFI code non-portable. Cheers, Simon