[Haskell] thread-local variables (was: Re: Implicit Parameters)

Frederik Eaton frederik at a5.repetae.net
Sun Jul 30 06:49:38 EDT 2006


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/


More information about the Haskell mailing list