[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: let-fluid problem
> I would like to argue against any DYNAMIC-WIND + SET! sort of
> "fluid variable" system. The problem is threads. If you have a
> thread model, then any thread switch involves unwinding up the
> stack to the common ancestor continuation, then winding down into
> the activated continuation. This seems unacceptably expensive; thread
> switch should be a low-overhead operation.
(Let us not confuse specification with implementation. When I
was (briefly) involved with C++ standardization, I learned the
"as-if rule." This refers to the fact that a feature may be
defined "as if" it were implemented in a particular way, but
an implementation is free to use a different implementation as long
as long as no well-defined program can tell the difference.)
A more fundamental problem with the fluid-let specification is that it
does not support a thread model that may have true parallel threads.
When the topic of "thread local variables" came up in the Guile
mailing list (see http://sourceware.cygnus.com/ml/guile/1999-03/)
I proposed a "deep binding" model of variable access
Each thread has an association list of fluid bindings.
When fluid-let is evaluated, it conses up a new association to the
front of the list. That becomes the current fluid binding
association list while the body of the fluid-let is evaluated.
The old list is restored when the fluid-let finishes.
(This can be implemented with the appropriate dynamic-wind.)
When a new thread is created, it initializes its fluid
binding list with the *current* list from the parent thread.
Thus all bindings are initially shared. When a non-local
variable is evaluated, the evaluator searches the current thread's
fluid binding list, and finds the first binding for the given name.
If none, is found, the global binding is returned.
When a set! is evaluated, it also searches the fluid bindigs list
of the current thread, and modifies the first association whose
name matches. If there is none, the global binding is modified.
This is of course only the semantic model; an actual implementation
may use caching or other thread-local storage.
This model is actually very general; it allows rather fine-grained
control over which variables are shared between which threads,
but using a very simple but general mechanism. (As such I think
it first very much in the spirit of Scheme.)
This model of thread-local storage has been implemented in Kawa.