Proposed change to ForeignPtr
Since requiring ForeignPtr.newForeignPtr would require preemptive concurrency (see previosu discussion), I propose the following changes: 1) Add these functions: makeForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO ForeignObj attachForeignPtrFinalizer :: ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO () 2) Remove newForeignPtr and addForeignPtrFinalizer Two variants on this proposal: 1) Reuse the old function names instead of inventing new ones. I don't care much either way. 2) Instead of removing the old functions, rename them and mark them as an optional extra. I think this would be a mistake - the GHC documentation is the right place to mention extensions which are not available on all ffi implementations. I have implemented makeForeignPtr in Hugs (I didn't do attachForeignPtrFinalizer yet because it'll take a bit longer to add that functionality and we can compile most (all?) of the hierarchial libs without it. -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
Alastair Reid <alastair@reid-consulting-uk.ltd.uk> wrote,
Since requiring ForeignPtr.newForeignPtr would require preemptive concurrency (see previosu discussion), I propose the following changes:
1) Add these functions:
makeForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO ForeignObj
I assume you meant makeForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a)
attachForeignPtrFinalizer :: ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO ()
What do you expect to happen if the finaliser calls a foreign exported function? (I am sorry, but I still haven't been able to closely look at the entire ForeignPtr discussion, so maybe this question was already answered there.)
2) Remove newForeignPtr and addForeignPtrFinalizer
Two variants on this proposal:
1) Reuse the old function names instead of inventing new ones.
I don't care much either way.
That's a tricky one. From the standards point of view, I am actually *very* reluctant to introduce new names. On the other hand, reusing the old names will lead to a couple of unhappy emails from people using the old interface again. Maybe we should have an -package old-ffi for compatibility.
2) Instead of removing the old functions, rename them and mark them as an optional extra.
I think this would be a mistake - the GHC documentation is the right place to mention extensions which are not available on all ffi implementations.
We have avoided optional extras so far and I don't see a reason to deviate from that policy now. Moreover, it is easy to define the old interface in terms of the new one that you propose (given you can handle callbacks in finalisers). Cheers, Manuel
I assume you meant makeForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a)
Oops, yes.
What do you expect to happen if the finaliser calls a foreign exported function?
Good question. I do not expect that to work on any platform that has difficulty implementing newForeignPtr (because you could use it to implement newForeignPtr). I don't know if it would be likely to work on GHC. I think the spec should say that it is an error or undefined depending on whether GHC supports reentrant finalizers or not.
That's a tricky one. From the standards point of view, I am actually *very* reluctant to introduce new names. On the other hand, reusing the old names will lead to a couple of unhappy emails from people using the old interface again.
But only a couple I conjecture. -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
Alastair Reid <alastair@reid-consulting-uk.ltd.uk> wrote,
What do you expect to happen if the finaliser calls a foreign exported function?
Good question.
I do not expect that to work on any platform that has difficulty implementing newForeignPtr (because you could use it to implement newForeignPtr).
I don't know if it would be likely to work on GHC.
SimonM, what do you think?
I think the spec should say that it is an error or undefined depending on whether GHC supports reentrant finalizers or not.
IMHO, it's a nice feature to have. I understand that the spec can't require it, as systems without preemptive threads can't implement it. However, it would be a pity if the new interfaces would mean that even systems that feature preemptive threads can't have it.
That's a tricky one. From the standards point of view, I am actually *very* reluctant to introduce new names. On the other hand, reusing the old names will lead to a couple of unhappy emails from people using the old interface again.
But only a couple I conjecture.
I read this as you would also (= like me) be in favour of keeping the old names. Right? Other opinions? Cheers, Manuel
That's a tricky one. From the standards point of view, I am > actually *very* reluctant to introduce new names. On the other > hand, reusing the old names will lead to a couple of unhappy emails from people using the old interface again.
But only a couple I conjecture.
I read this as you would also (= like me) be in favour of keeping the old names. Right?
I'm not sure which position you're preferring here. I lean a bit towards using the old names for the new functions (the ones with free functions) and finding new names for the old functions (the ones with closure arguments). -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
Alastair Reid <alastair@reid-consulting-uk.ltd.uk> writes:
I'm not sure which position you're preferring here. I lean a bit towards using the old names for the new functions (the ones with free functions) and finding new names for the old functions (the ones with closure arguments).
That would be my preference as well. Keep the existing standard names, but change their type signatures to reflect what Hugs and nhc98 can actually implement. Add new names with the old signatures for what ghc can additionally implement via its concurrency model. Regards, Malcolm
We seem to have a consensus on this one. We change the type of the existing functions to newForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a) addForeignPtrFinalizer :: ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO () For GHC, I propose to put the closure-based versions into an extra module (that's easy enough with the hierarchical libraries). This makes changing over old code easier, as it merely requires to alter the import and not all occurences of the functions. Any objections? Cheers, Manuel
Manuel M T Chakravarty <chak@cse.unsw.edu.au> wrote,
We seem to have a consensus on this one. We change the type of the existing functions to
newForeignPtr :: Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a) addForeignPtrFinalizer :: ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO ()
For GHC, I propose to put the closure-based versions into an extra module (that's easy enough with the hierarchical libraries). This makes changing over old code easier, as it merely requires to alter the import and not all occurences of the functions.
Any objections?
I have changed this in the spec now. I attach the wording used in the spec. Manuel -=- \item[newForeignPtr ::\ Ptr a -> FunPtr (Ptr a -> IO ()) -> IO (ForeignPtr a)] Turn a plain memory reference into a foreign object by associating a finalizer with the reference. The finalizer is represented by a pointer to an external function, which will be executed after the last reference to the foreign object is dropped. On invocation, the finalizer receives a pointer to the associated foreign object as an argument. Note that there is no guarantee on how soon the finalizer is executed after the last reference was dropped; this depends on the details of the Haskell storage manager. The only guarantee is that the finalizer runs before the program terminates. Whether a finaliser may call back into the Haskell system is system dependent. Portable code may not rely on such call backs. \item[addForeignPtrFinalizer ::\ ForeignPtr a -> FunPtr (Ptr a -> IO ()) -> IO ()] Add another finalizer to the given foreign object. No guarantees are made on the order in which multiple finalizers for a single object are run.
participants (3)
-
Alastair Reid -
Malcolm Wallace -
Manuel M T Chakravarty