[Haskell] thread-local variables

Simon Peyton-Jones simonpj at microsoft.com
Mon Aug 7 12:30:42 EDT 2006

| On Sat, Aug 05, 2006 at 02:18:58PM -0400, Robert Dockins wrote:
| > Sorry to jump into this thread so late.  However,  I'd like to take
a moment
| > to remind everyone that some time ago I put a concrete proposal for
| > thread-local variables on the table.
| >
| > http://article.gmane.org/gmane.comp.lang.haskell.cafe/11010

I'm cautious about jumping into this swampy topic, but here are some

* The thoughts that Simon and were considering about thread-local state
are quite close to Robert's proposal.  For myself, I am somewhat
persuaded that some form of implicitly-passed state in the IO monad
(without explicit parameters) is useful.   Examples I often think of are
	- Allocating unique identifiers
	- Making random numbers
	- Where stdin and stdout should go
In all of these cases, a form of dynamic binding is just what we want:
send stdout to the current thread's stdout, use the current thread's
random number seed, etc.  

* There's no need to connect it to *state*.  The key top-level thing you
need is to allocate what Adrian Hey calls a "thing with identity".
I'll call it a key.  For example, rather than a 'threadlocal'
declaration, one might just have:

	newkey foo :: Key Int

where 'newkey' the keyword; this declares a new key with type (Key Int),
distinct from all other keys.

Now you can imagine that the IO monad could provide operations
	withBinding :: Key a -> a -> IO b -> IO b
	lookupBinding :: Key a -> IO a

very much like the dynamic-binding primitives that have popped up on
this thread.

* If you want *state*, you can have a (Key (IORef Int)).  Now you look
up the binding to get an IORef (or MVar, whatever you like) and you can
mutate that at will.  So this separates a thread-local *environment*
from thread-local *state*.

* Keys may be useful for purposes other than withBinding and
thread-local state.  One would also want to dynamically create new keys:
	newKey :: IO (Key a)

* I agree with Robert that a key issue is initialisation.  Maybe it
should be possible to associate an initialiser with a key.  I have not
thought this out.

*  A key issue is this: when forking a thread, does the new thread
inherit the current thread's bindings, or does it get a
freshly-initialised set.  Sometimes you want one, sometimes the other,

On the GHC front, we're going to be busy with 6.6 etc until after ICFP,
so nothing is going to happen fast -- which gives an opportunity to
discuss it.  However it's just infeasible for the community at large to
follow a long email thread like this one. My suggestion would be for the
interested parties to proceed somewhat as we did with packages.

	* Make a Wiki page to describe a concrete proposal. 
	* Where there are design choices, describe them

	* If there are competing proposals that are incompatible, 
	   make more than one Wiki page. 

	* But strive to evolve to one or two, so that the rest of us are
	  faced with 10 proposals from 10 people!

This could happen on the GHC wiki or the Haskell wiki, though the latter
seems more appropriate.


More information about the Haskell mailing list