On Mon, Jul 31, 2006 at 03:09:59PM +0300, Einar Karttunen wrote: > On 31.07 03:18, Frederik Eaton wrote: > > I don't think it's necessarily such a big deal. Presumably the library > > with the worker threads will have to be invoked somewhere. One should > > just make sure that it is invoked in the appropriate environment, for > > instance with the database connection already properly initialized. > > > > (*) One might even want to change the environment a little within each > > thread, for instance so that errors get logged to a thread-specific > > log file. > > So we have the following: > 1) the library is initialized and spawns worker thread Tw > 2) application initializes the database connection and it > is associated with the current thread Tc and all the children > it will have (unless changed) > 3) the application calls the library in Tc passing an IO action > to it. The IO action refers to the TLS thinking it is in > Tc where it is valid. > 4) the library runs the callback code in Tw where the TLS state is > invalid. This is even worse than a global variable in this case.
If you have threads, and you have something which needs to be different among different threads, then it is hard for me to see how thread-local variables could be worse than global variables in any case at all. > Of course one can argue that the application should first initialize > the database handle. But if the app uses worker threads (spawned > before library initialization) then things will break if a library > uses TLS and callbacks and they end up running in threads created > before the library initialization. OK, sure. In certain situations you have to keep track of whether a function to which you pass an action might be sending it off to be run in a different thread. We've been over this. Perhaps users should be warned in the documentation - and in the documentation for exceptions as well. I really don't see that as a problem that would sneak up on people, since if you're passing an action to a function, rather than executing it yourself, then in most cases it should be clear to programmers that the action will run in a different context if not a different thread altogether. And if you want to force the context to be the same, you wrap the action in something restoring that context, just like you would have to do with your state transformer monad stack. Another way to write buggy code is to have it so bloated with extra syntax - e.g. with monad conversions, or extra function parameters, as you propose - that it becomes impossible to read and understand. Frederik -- http://ofb.net/~frederik/ _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell