[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
DYNAMIC-WIND vs. multi-processing
re: If users want to multi-process, they should use a concurrent language,
which straight, simple R4RS Scheme is not. CALL/CC with or without
DYNAMIC-WIND is not the way to do concurrency.
"Multi-tasking" is a different, somewhat less capable but certainly less
complex, concept than "concurrency" (I presume by the latter, you mean at
least that the execution model is designed to scale up smoothly from 1 to
2, and hence from 1 to "many", parallel processors). Still, Multi-tasking
is a very useful concept for the uniprocessor model.
But I agree wholeheartedly with your conclusion that "CALL/CC with or
without DYNAMIC-WIND is not the way to do concurrency." See the counter
point for the paragraph below.
re: Further, I do not think DYNAMIC-WIND-invoked-on-every-thread-switch is the
way to manage thread-shared state that needs to be in a particular
configuration while some thread is running -- what Gerry says RMS thought
it up for. Again, this model doesn't handle true parallel execution. An
example: suppose I wanted my threads to each have their own Unix current
working directory, so I had DYNAMIC-WIND do chdir's going in and cwd's
coming out. Then on every thread switch, I could do an (expensive, slow)
mutation of the shared process state to put each thread in his own
configuration of that state. But how do I model running threads on a
parallel processor, where more than one thread can execute at once?
CALL/CC and DYNAMIC-WIND don't handle this. I think a thread model should
have semantics that are independent of whether you are using a
uniprocessor or multiprocessor implementation.
That's a high cost to put onto the notion of "threads" -- that they must
be a capable model for concurrent parallel exection; but it is not an
unreasonable one. Having done so, there is an obvious implication that
is borne out by history. To wit:
Lucid's commercial Common Lisp product is a "shallow-bound" implementation,
and Multi-processing is accomplished by an equivalent of "DYNAMIC-WIND-
invoked-on-every-thread-switch" (and other tricks). However, when we began
work on QLISP--a queue-based multi-processor model for Common Lisp---we had
to abandon "shallow-binding" and go over to "deep-binding". It's not hard
to see that a shared-memory model must not communicate fluid state simply
by bashing globally-visible cells.
On the other hand---with 15 years of hindsight available---we didn't make
the mistake of confusing "deep binding" with "spaghetti stacks". The latter
is a model from the early 1970's that rolled dynamic variable state up with
execution control state into a context not unlike that required for first-
class continuations. This mixture proved to be not only semantically
confusing, and implementationally cumbersome, but ultimately not even what
was desired for the model of exectuion control state (the desired model was
"stack groups"---each processor with its own private control stack).
In conclusion: don't be seduced by superficial similarities between
CALL/CC and rugged concurency.
-- JonL --