Malcolm Wallace wrote (about PVar's, my proposed interface for useful mutable state in such a way that they can be implemented in NHC, GHC and Hugs): [snip]
I'll need to think some more about the details of PVars, but my first reaction is that they would very easy to implement. However, I fear it may be no good persuading me of their value if you cannot also persuade the other implementations to adopt them, so I'd like to hear what Hugs and ghc people have to say, especially whether they would also solve the problems with mutable shared state raised by Alastair. [snip] I don't see that it's necessary for us to come to a decision right now about PVars unless we want to put them in the FFI standard. Well we could do that, in the same way as we have unsafePerformIO, if it's what it takes us to see the back of this finalizers discussion, but I don't think it's particularly necessary; although I think it might be a good idea to have a standard definition of something like PVars so that people can do useful manipulations of mutable state in finalizers, such things don't really seem to me to belong in an FFI standard.
What's important now is that I think I've proved the point that there is an interface to mutable state which can be manipulated usefully and safely from Haskell finalizers in all of Hugs, GHC and NHC. Also, in view of Simon Marlow's patch and what Malcolm Wallace has said, it looks as if Haskell finalizers are at least implementable by all three. Therefore I see very little left to stop them going back into the FFI standard. I'm about to go on holiday for several days, so I look forward to coming back to find the whole issue safely buried in the FFI archives. 8-)
For the record, I am strongly in favor of Haskell finalizers, if a Mutable State extension were to be written, then it will have to address the issue with one of the solutions mentioned in this thread, but among other things, not having haskell finalizers seems to imply that we would need to add Weak pointers to the FFI. right now the only way to express dependencies between ForeignPtr's is via calling touchForeignPtr from the finalizer of another ForeignPtr, without the ability to call haskell from the finalizer this becomes impossible. The ability to tie the liveliness of ForeignPtrs together is quite important for many applications. Weak pointers would solve this issue, but haskell finalizers seems like a much better/simpler solution. not having this feature would make much of the foreign interfaces that exist today impossible or impractical. Just musing about the need some people have for ForeignPtrs to be deallocated deterministly, perhaps something like C#'s 'using' construct is in order which would enforce a stacklike allocation policy for ForeignPtrs... perhaps usingForeignPtr :: IO (ForeignPtr a) -> (ForeignPtr a -> IO b) -> IO b which guarentees the ForeignPtr allocated by the first computation will be finalized by the time the entire computation is executed. although perhaps this is not useful or a different type would be in order.. just throwing it out there... of course the same constraints one places on alloca and with* would be needed. and if we are adding things to the FFI spec, how about the empty data declaration? it is painfully simple to implement and would make FFI code a lot cleaner as it tends to depend heavily on placeholder types.. John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
For the record, I am strongly in favor of Haskell finalizers, if a Mutable State extension were to be written, then it will have to address the issue with one of the solutions mentioned in this thread,
We already have a perfectly good Mutable State extension. We know exactly what it looks like. It's already implemented by all compilers that support the FFI. There's really no question of putting off solving FFI-induced problems until such an extension exists. The extension exists now, the problem would have to be solved now.
The ability to tie the liveliness of ForeignPtrs together is quite important for many applications.
Can you give an example? (Maybe there's a paper that mentions it, I'll happily go read that.) -- Alastair
On Sat, Oct 12, 2002 at 06:03:07PM +0100, Alastair Reid wrote:
For the record, I am strongly in favor of Haskell finalizers, if a Mutable State extension were to be written, then it will have to address the issue with one of the solutions mentioned in this thread,
We already have a perfectly good Mutable State extension. We know exactly what it looks like. It's already implemented by all compilers that support the FFI.
There's really no question of putting off solving FFI-induced problems until such an extension exists. The extension exists now, the problem would have to be solved now.
True, but I just meant that the exact details of the Mutable State extension need not be specified in the FFI, if we can convince ourselves that a solution is possible, then we can move on with the FFI discussion. Personally, I think that a Mutable State specification that mentioned something about 'potentially concurrent' computations is probably useful as they arrise in several places, not just finalizers. if I thought this problem was an isolated example which only pertained to finalizers then just C finalizers might be a solution, but we are going to have to tackle this eventually, and probably soon. 'potentially concurrent' computations come up whenever you want to write portable library code which makes use of state, if there is a chance it will ever be used in an implementation with concurrency. They would also be useful if an implementation wanted to implement asyncronous signal handling without invoking concurrency. My solution to this problem has been part of my autoconf script which detects the presence of MVars and when they do not exist, defines newMVar, modifyMVar, swapMVar, readMVar, and writeMVar in terms of IORef. that way I know my libraries will work everywhere independent of the presence of concurrency. this solution seems to work rather well as you cannot deadlock the system with just those primitives.
The ability to tie the liveliness of ForeignPtrs together is quite important for many applications.
Can you give an example? (Maybe there's a paper that mentions it, I'll happily go read that.)
at least two papers mention it that i know of off the top of my head, the paper which describes the implementation of Weak, ForeignPtr etc. It claims one of the motivations for weak pointers is to inform the garbage collector of dependencies which may not exist on the haskell side of things. they use interfacing with C code as an example. the other paper is the FFI spec itself! the section for touchForeignPtr says that it should be used to express dependencies between foreignptrs by calling it in the finalizers of other foreignptrs. oddly enough, that means the spec is currently quite internally inconsistant since we cannot make such calls. (!!) I personally have used it in both my ncurses and openssl interfaces, in openssl you have opaque structures which contain links to other opaque structures. in haskell they are represented by ForeignPtr's with finalizers that destroy them, however a common thing to do is create an RSA object and place it within some other object. once the haskell reference to the RSA object disapears suddenly it is freed out from under the other object and all heck breaks loose! the solution is to create a weak link from the encryption object to the RSA object making sure it lasts as long as the encryption object. right now the only ways to do that are using 'mkWeak' to create the link, or touchForeginPtr rsa in the encryption object finalizer to make sure it still exists (as it recommends as the portable way in the FFI spec.) John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
John Meacham <john@repetae.net> writes:
Just musing about the need some people have for ForeignPtrs to be deallocated deterministly, perhaps something like C#'s 'using' construct is in order which would enforce a stacklike allocation policy for ForeignPtrs...
If you need deterministic finalisation, we already have IO.bracket: bracket :: IO a -> (a->IO b) -> (a->IO c) -> IO c The first argument generates the value 'a', the second finalises it even in the presence of exceptions, and the third argument is the action that uses the value. Just instantiate the type variable 'a' to Ptr rather than ForeignPtr.
and if we are adding things to the FFI spec, how about the empty data declaration? it is painfully simple to implement and would make FFI code a lot cleaner as it tends to depend heavily on placeholder types..
Hugs and ghc already have it (AFAIK). I recently added it to nhc98. Do you think it should become a formal part of the FFI standard? Or is it best left as another "common" extension of Haskell'98 that just happens to be implemented everywhere? Regards, Malcolm
and if we are adding things to the FFI spec, how about the empty data declaration? it is painfully simple to implement and would make FFI code a lot cleaner as it tends to depend heavily on placeholder types..
Hugs and ghc already have it (AFAIK). I recently added it to nhc98. Do you think it should become a formal part of the FFI standard? Or is it best left as another "common" extension of Haskell'98 that just happens to be implemented everywhere?
I think it's main use is in the ffi so it makes sense to add it there. I don't feel that strongly about this though. A
On Mon, Oct 14, 2002 at 11:07:27AM +0100, Malcolm Wallace wrote:
and if we are adding things to the FFI spec, how about the empty data declaration? it is painfully simple to implement and would make FFI code a lot cleaner as it tends to depend heavily on placeholder types..
Hugs and ghc already have it (AFAIK). I recently added it to nhc98. Do you think it should become a formal part of the FFI standard? Or is it best left as another "common" extension of Haskell'98 that just happens to be implemented everywhere?
yeah, I would like to see the extension in the FFI, because it will probably never make it in anywhere else and it makes FFI code so much cleaner/more readable. I'd almost like to see it considered a 'misprint' in the haskell report and fixed there, but I'd settle for the FFI. Since every compiler supports it, we should put it in, rather then encourage everyone to write technically 'non-portable' code, by providing the perfect use for it in the FFI but not the extension itself. John -- --------------------------------------------------------------------------- John Meacham - California Institute of Technology, Alum. - john@foo.net ---------------------------------------------------------------------------
[snip] I don't see that it's necessary for us to come to a decision right now about PVars unless we want to put them in the FFI standard.
But what if we can't agree on something like PVars or we decide that Haskell finalizers plus yet another synchronization mechanism is worse than C finalizers? -- Alastair
Alastair Reid wrote:
[snip] I don't see that it's necessary for us to come to a decision right now about PVars unless we want to put them in the FFI standard.
But what if we can't agree on something like PVars or we decide that Haskell finalizers plus yet another synchronization mechanism is worse than C finalizers?
Well the first problem (not agreeing on something) is a problem for the Mutable State Standardisation committee (not us). As for "Haskell finalizers plus yet another synchronization mechanism", PVar's are not "yet another synchronization mechanism" because the whole point is that NHC at least has no synchronization mechanism, and if we are going to have a standard synchronization mechanism (which as I've argued is a good idea) something like PVars are needed, if we are to take it that P/V/MVars are all impossible. Even if there were no FFI standard, I think PVars or something like them would be a good idea, otherwise it would be impossible to write functions like Alastair's newObject/killObject so that they could be ported between NHC and other Haskell systems.
participants (4)
-
Alastair Reid -
George Russell -
John Meacham -
Malcolm Wallace