| > Yesterday evening I was experimenting with an electronic circuit, and | > the fumes from the soldering must have entered my brain and triggered | > something there Strangely enough, Simon and I had actually come up with another variant, which I believe is simpler than both the original and Wolfgang's proposal. I've updated threads.tex and posted Postscript here http://research.microsoft.com/~simonpj/tmp/threads.ps (It may be a few minutes before it updates; I'll email it too.) Simon
Strangely enough, Simon and I had actually come up with another variant, which I believe is simpler than both the original and Wolfgang's proposal.
Yes, that seems to be what Daan was talking about. I'm sorry to say that I don't really like it... *) It violates requirement #4 "The specification shouldn’t explicitly require lightweight “green” threads to exist." OK, I wrote that requirement, and I might be the only one who cares. But I still think that the existance of lightweight threads should not somehow become a feature of the Haskell language. *) Using the system requires a lot of knowledge of the thread allocation issues, as all thread management has to be done manually. Special combinators like nonBlocking will have to be used far more often than the "threadbound" combinator of proposal #2. *) The blocking behaviour of foreign calls is specified with a bias towards GHC's implementation. Let's assume I have a Haskell interpreter that runs in just one thread. Now I want to add FFI support for multiple "foreign" OS threads without too much effort, and without caring for top-notch performance. I'd probably keep the interpreter running in just one thread, and send messages to other OS threads whenever I want to execute a foreign call. In this situation, threadsafe calls come for free (as far as implementation complexity is concerned). If I allow multiple Haskell threads to be bound to one OS thread, there would be blocking, but the behaviour would be different from the proposed behaviour; other Haskell threads bound to the same OS thread would not block until they issue a foreign call. *) Blocking "safe" calls will keep surprising newbies (they did surprise me once...). *) Blocking "safe" calls are a problem for libraries and for large software projects. a) If I use an IO action from a library, how do I know whether it uses the nonBlocking combinator internally? The library developer might have considered 'nonBlocking' to be too expensive or (s)he might not have been aware of the blocking behaviour of "safe" calls. To be really sure, I'd have to wrap every library call with the nonBlocking combinator, even when it's not necessary, which will be cumbersome and inefficient. [The same danger exists with "unsafe", but at least that's clearly marked as being unsafe...] b) Let's assume I'm writing a library. I want to use some foreign API that relies on thread local state internally (without exposing that fact to my library's users). I don't know whether my Haskell thread is the only Haskell thread in the OS thread, so I have to spawn a new OS thread for myself. If the program that uses the library happens to be single-threaded, that's wasted effort again. [This could probably be fixed by providing a way to query the number of threads bound to an OS thread] *) Having to deal with which Haskell threads are mapped to which OS threads seems too low-level. After all, we are willing to accept the complexity of a Haskell RTS in order to avoid always using C... I'm also willing to accept some added complexity in order to not have to manually manage all my OS threads. *) The formal semantics might be simpler, but as far as I can tell, the GHC implementation of Proposal III would be no simpler than the implementation of Proposal II. OK that's all for now, maybe I'll be back with more. But I'm sure you can utterly refute several of those arguments... Cheers, Wolfgang
I haven't looked at the new proposal closely but I'm very disturbed when Wolfgang reports:
*) It violates requirement #4 "The specification shouldn’t explicitly require lightweight “green” threads to exist."
*) The blocking behaviour of foreign calls is specified with a bias towards GHC's implementation. [...]
If true this will make it harder to implement the proposal in Hugs and NHC. Also, I think the experience of most language designs that I know of is that if your design reflects too much of your current implementation technique, then you're creating problems for yourself in the future. (Examples: ML modules, C typedefs, most C++ features, ...) -- Alastair
One more thing: Under Proposal III, what does the following code do: foreign export ccall foo :: IO () foo = forkIO bar bar = putStrLn "HelloWorld" >> bar Cheers, Wolfgang
"Simon Peyton-Jones" <simonpj@microsoft.com> wrote,
| > Yesterday evening I was experimenting with an electronic circuit, and | > the fumes from the soldering must have entered my brain and triggered | > something there
Strangely enough, Simon and I had actually come up with another variant, which I believe is simpler than both the original and Wolfgang's proposal.
I've updated threads.tex and posted Postscript here http://research.microsoft.com/~simonpj/tmp/threads.ps
I like this proposal best (of the three in the document). In particular, it is very simple. Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote,
*) It violates requirement #4 "The specification shouldn� explicitly require lightweight �reen�threads to exist." OK, I wrote that requirement, and I might be the only one who cares. But I still think that the existance of lightweight threads should not somehow become a feature of the Haskell language.
Not a feature of Haskell 98, but we are talking about a concurrency extension anyway. In fact, I think, we should have an Addendum that covers all concurrency support (lighweight and OS threads) in one go. If anything, this is only going to make the overall system simpler. So, IMHO, we should negate your requirement.
*) Using the system requires a lot of knowledge of the thread allocation issues, as all thread management has to be done manually. Special combinators like nonBlocking will have to be used far more often than the "threadbound" combinator of proposal #2.
The FFI design so far has always tried to provide minimal extensions. Cheers, Manuel
Manuel M T Chakravarty wrote:
Wolfgang Thaller <wolfgang.thaller@gmx.net> wrote,
*) It violates requirement #4 "The specification shouldn't explicitly require lightweight "green" threads to exist." OK, I wrote that requirement, and I might be the only one who cares. But I still think that the existance of lightweight threads should not somehow become a feature of the Haskell language.
Not a feature of Haskell 98, but we are talking about a concurrency extension anyway. In fact, I think, we should have an Addendum that covers all concurrency support (lighweight and OS threads) in one go. If anything, this is only going to make the overall system simpler.
It would be the first place where implementations of Concurrent Haskell are required to provide lightweight threads. Also, I expect Concurrent Haskell to be here to stay for some time, so tying the concurrency extension to the implementation technique that happens to be "standard" right now would IMHO still be a mistake.
*) Using the system requires a lot of knowledge of the thread allocation issues, as all thread management has to be done manually. Special combinators like nonBlocking will have to be used far more often than the "threadbound" combinator of proposal #2.
The FFI design so far has always tried to provide minimal extensions.
Haskell so far has tried to be "safe" to use; this manual thread management is not safe, it smells like it's going to generate lots of bugs. This would be the first time that Haskell (+concurrency extension+libraries) is less safe than C (+OS libraries) in a particular area (threading). You just don't get that strange blocking behaviour in C. It could even be argued that Proposal 3 is, in fact, not a minimal extension at all; If we have a multi-OS-thread Haskell implementation, we can implement Proposal 2 by threadbound = id ... but Proposal 3 can only be implemented by changing to a light-weight-thread based scheduler. The explicit thread management of Proposal 3 requires run time systems to support situations where 3 Haskell threads are running in OS thread A, and two more Haskell threads are running in OS thread B. Who needs that, and what for? It also requires runtime systems to actually use the native thread that a Haskell thread is bound to for it's execution (which happens to be the natural choice for GHC's implementation). It should be possible to implement Proposal 2 for Hugs; my current impression is that Hugs' Concurrency implementation would have to be redone from scratch to support Proposal 3. Cheers, Wolfgang
participants (4)
-
Alastair Reid -
Manuel M T Chakravarty -
Simon Peyton-Jones -
Wolfgang Thaller