On Sun, Jul 30, 2006 at 12:35:42PM +0300, Einar Karttunen wrote:
On 29.07 13:25, Frederik Eaton wrote:
I think support for thread-local variables is something which is urgently needed. It's very frustrating that using concurrency in Haskell is so easy and nice, yet when it comes to IORefs there is no way to get thread-local behavior. Furthermore, that one can make certain things thread-local (e.g. with withArgs, withProgName) makes the solution seem close at hand (although I can appreciate that it may not be). Yet isn't it just a matter of making a Map with existentially quantified values part of the state of each thread, just as the program name and arguments are also part of that state?
Are thread local variables really a good idea in Haskell?
Yes.
If variables are thread local how would this combinator work:
Do read the code I posted. Please note I'm not suggesting that *all* variables be thread local, I was proposing a special data-type for that.
withTimeOut :: Int -> IO a -> IO a withTimeOut tout op = mdo mv <- newEmptyMVar wt <- forkIO $ do try op >>= tryPutMVar mv >> killThread kt kt <- forkIO $ do threadDelay tout e <- tryPutMVar mv $ Left $ DynException $ toDyn TimeOutException if e then killThread wt else return () either throw return =<< takeMVar mv
Would it change the semantics of the action as it is run in a different thread (this is a must if there are potentially blocking FFI calls).
No, because the thread in which it runs inherits any thread-local state from its parent.
Now if the action changes the thread local state then it behaves differently. Do we really want that?
I'm not sure what you're suggesting. The API I proposed actually doesn't let users discover when their actions are running in sub-threads. (Can you write an example using that API?) However, even if it did, I don't see a problem. Do you think that we should get rid of 'myThreadId', for instance? I don't.
Usually one can just add a monad that wraps IO/STM and provides the variables one needs. This has the good side of making scoping explicit.
That's easier said than done. Sometimes I take that route. But sometimes I don't want 5 different monads wrapping each other, each with its own 'lift' and 'catch' functions, making error messages indecipherable and code difficult to read and debug. Do you propose creating a special monad for file operations? For network operations? No? Then I don't see why I should have to make a special monad for database operations. Or, if the answer was "yes", then fine: obfuscate your own code, but please don't ask me to do the same. Let's support both ways of doing things, and we can be different. Frederik -- http://ofb.net/~frederik/