[Seaside] Seaside Internals

Stephen Pair stephen at pairhome.net
Mon Sep 8 17:33:48 CEST 2003


Avi Bryant wrote:

>On Mon, 8 Sep 2003, Stephen Pair wrote:
>
>  
>
>>Those links seem to only argue in favor of having continuations evaluate
>>an unwind behavior.  Where are the arguments against?  I can't think of
>>any reason why a normal use of continuations shouldn't invoke the unwind
>>behavior of the calling (and terminating) stack.  In my opinion, any
>>flow control contructs (non local returns, exception handling,
>>continuations, etc) should honor requests to #ensure: (and friends).
>>    
>>
>
>Stephen,
>
>The argument isn't really whether or not continuation invocations should
>evaluate #ensure: blocks, but when or which ones.
>
>The problem is that part of the contract of an ensure block is that it's
>the *last* thing to get evaluated - when you have
>
>[A] ensure: [B],
>
>you expect B to only get evaluated once A is done - and it may well be
>very broken to evaluate anything in A after B has done its thing.
>
>But if I capture a continuation inside A, then exit from A (evaluating
>B), I now have the power to do exactly that - jump back into the middle
>of A.  And when you then leave again, does B get evaluated a second time,
>a third?
>

I see.  I was speaking to the common case where you are resuming a 
continuation and the active stack is being abandoned (without a 
continuation to resume it)...in that case, my expectation is that unwind 
behavior would be invoked.  But, I see your point about resuming 
continuations that happen to be inside contexts that have unwind 
behavior.  A solution may be to always resume a continuation in its own 
process (allowing the caller to continue processing normally while the 
continuation runs in another process) and to provide for a mechanism 
that can restrict certain continuations to just a single invocation.  A 
continuation that has unwind behavior in it's stack would be restricted 
to a single invocation.  For example, assuming that a continuation is 
resumed on a separate process, the following would be illegal for a 
continuation that has unwind behavior:

    aContinuation resume; resume

The first would be allowed, the second disallowed (with a cannot resume 
exception or something).  If you were to extend this to accommodate 
exceptions, then you would also likely want continuations that cannot be 
resumed at all.  And, there may even be situations where you'd want to 
restrict continuations to some arbitrary number of invocations.

Looking at most uses of #ensure: or #ifCurtailed:, allowing multiple 
invocations of a continuation inside those blocks would make absolutely 
no sense...that is, unless I could guarantee that at most one 
continuation reached the ensure block.  Which essentially means that I'd 
want to have a continuation disabled once any invocation reached a 
certain level in the stack.  Perhaps a Continuation that would be 
expired after the current context completes would be useful?  Consider this:

    self one.
    [Continuation currentDo: [ :cc | ^cc ].
    self two]
       ensure: [self three].

We could conceivably constuct a continuation such that once any 
invocation of the continuation proceeds beyond the initial context, 
other invocations would be disallowed.  We could further restrict the 
continuation such that one and only one continuation could be active at 
any given time.

>So the general gist of those papers is to find a way such that B gets
>evaluated exactly once, when you promise that you're truly done with A -
>or, alternatively, to invalidate any continuations you've captured inside
>A as soon as you evaluate B.
>
>It's *not* as simple as just always evaluating B whenever you leave A (for
>example by invoking another continuation).
>
>In a Seaside context, my recommendation is simply this: *do not show a
>page to a user from within a block that is protected by #ensure:*.  "[self
>call: Foo] ensure: [...]" is just bad news.
>
>  
>
>>Btw, what about changing the protocol of continuations from #value to
>>#resume (I think the arguments in favor of this change were that there
>>is more of an expectation of non-normal flow control happening with
>>#resume)?
>>    
>>
>
>For now it's too useful that they be polymorphic with blocks - I guess it
>could have both #resume and #value...
>

Or you could simply wrap the continuation in a block or message send.  
To me, having a continuation understand #value is like having a Process 
(or a stack) understand #value.  It obscures the true intention.  If you 
really need the convenience, why not implement the following method on 
Continuation:

asValuable

    ^[self resume]

or, even better (esp without block closures):

asValuable

    ^MessageSend receiver: self selector: #resume

>> Also, I'd like to see another method on a continuation that
>>will create and schedule another process to resume a continuation (and
>>leave the current stack alone)...maybe that's already there though.
>>Something like:
>>
>>fork
>>
>>    [self resume] fork
>>    
>>
>
>You've got to be careful here - the Continuation class that comes with
>Seaside is not thread safe, and it's not trivial to write one that is
>(although if Anthony's "context tags" made it ito 3.6, that makes it
>easier).
>  
>

Could you explain that a little more.  Do you mean that a continuation 
cannot be concurrently invoked?  I suspect that's the case since it 
doesn't look like you're copying the context objects in #restoreValues 
...btw, didn't you copy the stack in previous versions?  It doesn't seem 
like that should be so difficult to either prevent, or accommodate.

>What's the common use you see for that?
>

I just don't like the fact that sending #value to a Continuation trashes 
the calling stack (with no unwind)...it seems like that shouldn't be 
necessary.

>>One of these days, we'll have to think about reconciling continuations
>>and exception handling (where an exception would hold a continuation and
>>a handler would run in a different branch off the same stack as the
>>continuation (instead of being lopped onto the bottom of the stack)).
>>    
>>
>
>One of these days.  ;)
>

- Stephen



More information about the Seaside mailing list