[ENH] ContextCleanup-ajh ( [cd][er][et][su] extremely useful; unclear about ContextTag )

Avi Bryant avi at beta4.com
Thu Jun 26 17:43:37 UTC 2003


On Thu, 26 Jun 2003, Andreas Raab wrote:

> About the only change that isn't completely obvious to me is the
> introduction of ContextTag for identifying references to contexts. Using
> a context's receiverMap instance variable 'because it's unused' looks
> like a hack (why not use a registry? if they are only needed for
> continuations it seems that the speed implications of storing it
> internally vs. in a registry should be irrelevant) and it is unclear
> where exactly the advantage of using ContextTag is. While test cases are
> provided they do not illustrate any of the advantages of using context
> tags.

I can't speak to the use of receiverMap.  However, I can try to explain
the advantages of ContextTag.  Occasionally, an object somewhere in the
stack will be pointing a a context earlier in the stack - for example, the
"home" of a BlockContext:

MethodContextA <------
   |                 |
MethodContextB    (home)
   |                 |
BlockContextC  -------

A simple minded implementation of Continuation will do a shallow copy
of the entire stack, recursively replacing each sender in turn.  In the
above case, the BlockContext ends up pointing to the wrong home:

MethodContextA <--           MethodContextA'
   |             |               |
MethodContextB   |           MethodContextB'
   |             |               |
BlockContextC    ---(home)-- BlockContextC'

Similar situations occur if you try to copy the stack during exception
handling.

In Seaside, my first solution was that whenever I copied a stack, I
manually walked it looking for BlockContexts and fixing up the home
pointers.  This mostly worked, although there were still times during
exception handling where capturing a continuation will break.  These were
obscure enough that I never bothered writing code to fix them.

Very recent versions of Seaside take advantage of the fact that
Continuations are tied to Processes - I'm always executing a Continuation
in the same Process, which means I'm never executing two copies of the
same stack at the exact same time.  Thus, instead of ever actually using a
copied stack, invoking a continuation reuses the original context objects,
restoring their pc/sender/etc values as needed.  Because the identity of
the contexts never changes, "home" references and so on don't need any
special treatment.

The idea of a ContextTag is that rather than ever holding directly onto
context objects that are above you in the stack, you hold onto a "tag"
object that is unique for that context in that copy of the stack - to find
the actual context, you walk the senders until you find one with the right
tag.

This means that when you copy the stack, as long as you adjust the sender
references, everything else will follow.  It's a nice, general, elegant
solution.

Personally, however, I would be happy enough not to have ContextTag, and
to simply impose the restriction (as current versions of Seaside do) that
you can't have multiple concurrent invocations of the same Continuation.
This is not that uncommon a restriction - I know that Ruby and PLT Scheme
both have it as well.

Hope this clarified things somewhat.

Avi




More information about the Squeak-dev mailing list