[squeak-dev] #ifCurtailed - why the "complete := true" line?

Jaromir m at jaromir.net
Sat Feb 13 19:22:14 UTC 2021


Hi Tobias,

>> Hi,
>> I can't figure this one out - is the value of /complete / in #ifCurtailed
>> method used somewhere? 

> Yes.

That’s a great help, thanks! So I understand “complete” marks contexts that
have already been processed (unwound) during an abnormal return (in
#resume:through:) or, in case of a normal return it just marks normal
completion of #ensure/#ifCurtailed.

Just to be sure: there’s a close interplay between e.g. #ensure and
#resume:through: but NO interplay between #ensure and #ifCurtailed, right?

And finally, is there a simple example where “complete” plays a role? It
seems to me that if #resume:through: unwinds contexts it never gets to
unwind the same context twice and if the #ensure protected block returns
normally no unwinding even happens.

I tried to remove “complete” from the #ensure/#ifCurtailed code and all my
naive examples work as before :)



> But first thing to notice is that #ensure: uses the same primitive and the
> same names and oder of local variables.
>
> In both methods, the comment states:
>  " The VM uses prim 198 in a context's method as the mark for an
> ensure:/ifCurtailed: activation"
>
> But more so:
>
> Look at Context>>unwindTo:
>
> unwindTo: aContext
>
> ​    | ctx unwindBlock |
> ​    ctx := self.
> ​    [(ctx := ctx findNextUnwindContextUpTo: aContext) isNil] whileFalse:
> [
> ​            (ctx tempAt: 2) ifNil:[
> ​                    ctx tempAt: 2 put: true.
> ​                    unwindBlock := ctx tempAt: 1.
> ​                    unwindBlock value]
> ​    ].
>
> In a Context, that is the "running" form of a Block, tempAt: 1 is the
> argument of #ifCurtailed:/#ensure:.
> and tempAt: 2 is "completed". So: the context will be marked as being
> completed either via #ifCurtailed: directly or via #unwindTo:.  However,
> in #ensure:
>
> ensure: aBlock
>         | complete returnValue |
>         <primitive: 198>
>         returnValue := self valueNoContextSwitch.
>         complete ifNil:[
>                 complete := true.
>                 aBlock value.
>         ].
>         ^ returnValue
>
> The aBlock will only be run if the action was not completed yet.

Now this confused me: if the protected block returns normally, that means no
unwinding has happened and thus “complete” must be nil and aBlock will
always be evaluated.

Conversely, if the protected block returned abnormally I thought it meant
the process would never reach the condition and the aBlock would never be
run here (but on the unwind path instead).

Where am I wrong?

(I used this to explore: [x := thisContext sender explore. ^1] ensure: [x
explore] )

Thanks again!
Jaromir



> "complete" can be set from the outside as can be seen in #unwindTo:.
> It is also visible, that #unwindTo: and #ensure: have a similar structure,
> but #unwindTo: operates on the data structure of the "running" code.
>
> See also in Context: #restart #resume: #resume:through:  or
> Process>>#terminate.
>
> I hope this helps :)
>
> Best regards
>         -Tobias



--
Sent from: http://forum.world.st/Squeak-Dev-f45488.html


More information about the Squeak-dev mailing list