Re: Concurrency (was: Re: [GUI] Re: events & callbacks)

Sorry in advance for the long post... Daan Leijen wrote:
Please think a little bit longer before voting a "big NO". If we want to make progress we shouldn't rule out a solid and simple solution based on shaky arguments.
My vote remains a big NO for now because I don't consider my arguments shaky. Of course, I'll keep thinking about it, and as soon as I discover the error of my ways, I'll change my vote. If I remain too stubborn, a single "NO" vote isn't a majority for no, so don't worry... ;-)
2e) All haskell call backs are run in a single OS thread (the "GUI thread"). Calls to the CGA can be made at any time from any Haskell thread that run within the GUI thread.
My reservation remains that there is no way for a standard Concurrent Haskell program to control which Haskell threads run in which OS thread. The current proposal for "bound threads" (see ffi@haskell.org) will allow some control, but for the sake of simplicity it doesn't support explicitly binding multiple Haskell threads to one OS thread.
1) What if Haskell automatically decides to run Haskell threads in some other OS thread? First, I believe that an automatic system would be a mistake,
... which, if you think that it is a mistake, this mistake has already been made. Threadsafe already exists.
but secondly, such system will surely provide a forkIO variant that runs the Haskell thread in the same OS thread.
... which would defeat the purpose of "threadsafe", which was to prevent the FFI from blocking other Haskell threads unpredictably.
However, I don't really want to discuss OS threads/Haskell threads here, it is enough to know that this formulation does *not* rule out future GHC's or future OS multi threaded systems. )
Do we know this? GHC does not guarantee that multiple Haskell threads are run in a certain OS thread. It most definitely rules out the current version of GHC (with a special configure switch) and everything that was planned for the next version. As I said, there is no defined mapping between Haskell threads and OS threads. So we can't say "... from the same OS thread", because a Haskell programmer currently has no way to say "fork a new Haskell thread in the same OS thread as the current Haskell thread". That leaves us with two options that I can think of: a) Restrict everything to one *Haskell* thread b) Don't restrict anything - require implementations to do proper synchronization or, if the backend requires it, even to channel everything to the right thread. b) is of course more work, and people have had doubts that it is implementable. I'm convinced that it can be implemented, and that it's not too difficult, but of course we can't go ahead with this until all backend implementors are convinced that it's possible. a) probably won't be popular with people who want to experiment with concurrency for GUIs.
You are right that different Haskell threads can interact with each other in devious ways by modifying global state... this is called the IO monad :-) There is no way you can solve this problem in general, and for the GUI it may involve a lot of overhead.
*This is the responsibility of the user when using concurrency*. In your example, it is a classic multiple writers, single resource pattern.
I was thinking of situations where the state is not visible to the user of the CGA. Suppose there was a function like messageBox :: String -> IO () in the CGA. On Win32, this could be implemented by a call to the Win32 MessageBox function. On MacOS, there is no predefined function for that, so the implementation would consist of the following steps: 1) Create a dialog window with the message 2) Show the window & bring it to the front 3) Run the modal event loop 4) Close the window If two Haskell threads (possibly even running in the same OS thread) attempt to call messageBox, then there'll be a race condition here in the Mac version, but not on the Windows version. If we say that that is the application's responsibility, then the application developer would need to know the implementation of the Mac OS backend in order to write a correct program. An average programmer would not forget about locking, test it on Windows, and it would work. On Mac OS, we'd get hard-to-reproduce bugs.
Well, you introduced heavy weight synchronisation that has to be wrapped around *every* foreign call to the GUI.
No. I'm talking about normal Haskell synchronization primitives. As there's still only one Haskell thread running at one time, they are as lightweight as ever.
Furthermore, you imply that a worker thread should be run in a different OS thread to keep everything reactive.
That will happen automatically in future versions of GHC. If you want a foreign call and a Haskell thread to run in parallel, you need at least two OS threads. Idle callbacks are more inefficient.
However, OS threads are rather heavy weight and it may take longer to start one than the processing takes. In contrast, Haskell threads are extremely light-weight and fast.
The RTS pools OS threads. In GHC, I don't expect a complex concurrent GUI program to spawn more than about three OS threads.
I appreciate the work you are doing on supporting OS threads in GHC -- it is interesting to see how it will work out. However, for the CGA it is enough to run in a single OS thread. The specification should just allow room for use of the CGA in the context of multiple OS threads -- but it doesn't have to support all this automatically as I think that the issues are more subtle than initially appreciated. Evolution, not revolution!
Of course. I don't insist on requiring CGA implementations to do proper synchronizing, but I think that a) it's not any more difficult than any other problem involving concurrency b) Prohibiting Concurrency and limiting everything to one Haskell thread would be very restrictive c) The middle ground that you proposed, that is to allow multiple Haskell threads to call the CGA as long as they all run in one OS thread, doesn't exist, as a Haskell thread is never guaranteed to run in a certain OS thread. d) Achieving the amount of synchronization & serialization that is automatically provided by a single-threaded RTS is _really simple_, so the number of OS threads should be a non-issue. The question is, do we want to support concurrency or not? Cheers, Wolfgang
participants (1)
-
Wolfgang Thaller