This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: thread local variables


Per Bothner <bothner@cygnus.com> writes:

> > For instance, when you spawn a new thread, which of the original
> > threads' bindings should be shared with the new thread?
> 
> They are all shared, until the new thread does another fluid-let.

Right.  Bindings created with fluid-let are thread local, so you have
to use a different binding form to change the value of a truly global
variable.  And you have to sprinkle the knowledge about which vars
should be handled with which binding form all over the code, every
time a binding of one of these variables is made.

Ugh.  This makes code reuse harder, and it's ugly, and that's why the
parameter abstraction is useful.

> > One can imagine for instance that the current output port could be shared
> > between the two threads.  It's not hard to imagine other uses:
> > let's say you have a cl-style parameter *print-circle*, one might
> > want to have this shared across threads, and have changes to it
> > automatically protected with a mutex.
> 
> But it is harder to imagine a use that is not handled by fluid-let.

Yes, but will it be _tedious_ to use fluid-let?  What do you think
about my comment above, about where in the code you have to specify
the type of binding?  It's a waste of brain power to require the
programmer to remember always and everywhere whether a global variable
should be shared across threads or not.

> > Having an abstraction like this is very powerful, and I expect that it
> > would allow other important features to be implemented easily and
> > cleanly.
> 
> Please show me a useful example that I can't do with fluid-let.

"Can't do" is not a very useful benchmark, because design is always a
question of convenience/aesthetics.  You can write your programs in
assembly, and do just fine without parameters, and I can't really
argue with that.  But it doesn't mean that parameters aren't a great
feature for a multi-threaded Scheme.

A perhaps better question is, do parameters provide a useful and well
designed abstraction that fluid-let does not provide?  You didn't
expend the least bit of effort trying to answer that question.

I'll try to formulate an example using *print-circle*.  Imagine a
program with two threads, operating on a circular data structure.
Thread a determines that there is a chance that the data structure is
circular, so it tries to prepare the world like this:

(fluid-let ((*print-circle* #t))
  (do-stuff-with-obj)
  (put-object-onto-b-inq obj)
  (wait-for-b-to-finish-processing obj))

Now thread b will take over, but it won't necessarily have
*print-circle* set to #t.  So I guess I just wanted to use
*print-circle* as a global var, which changes the above to:

(dynamic-wind
  (lambda () (set! *print-circle* #t))
  (lambda ()
    (do-stuff-with-obj)
    (put-object-onto-b-inq obj)
    (wait-for-b-to-finish-processing obj))
  (lambda () (set! *print-circle* #f)))

Now I want to reuse the above code in another application where
*print-circle* should not be shared, but should be thread-local. Doh!

With parameters, this code would be:

(parameterize ((*print-circle* #t))
  (do-stuff-with-obj)
  (put-object-onto-b-inq obj)
  (wait-for-b-to-finish-processing obj))

And it would work whether the user wanted *print-circle* shared across
threads or not.  Your point is correct of course: you can code the
above without parameters.  It's just ugly, difficult to reuse, and an
unnecessary burden on the programmer.

I'm not completely happy with the example I formulated, but I still
think that this feature is very useful.  It unifies the concepts of
binding thread-local and truly global variables, which makes the code
that uses these types of variables simpler.

-russ

--
"It seems certain that much of the success of Unix follows from the
readability, modifiability, and portability of its software."
             -- Dennis M. Ritchie, September, 1979