Hi, I can't figure this one out - is the value of /complete / in #ifCurtailed method used somewhere? Very confusing ;) Thanks a lot! Jaromir
ifCurtailed: aBlock | complete result | <primitive: 198> result := self valueNoContextSwitch. complete := true. ^result
-- Sent from: http://forum.world.st/Squeak-Dev-f45488.html
Hi
On 13. Feb 2021, at 12:55, Jaromir m@jaromir.net wrote:
Hi, I can't figure this one out - is the value of /complete / in #ifCurtailed method used somewhere? Very confusing ;) Thanks a lot! Jaromir
ifCurtailed: aBlock | complete result | <primitive: 198> result := self valueNoContextSwitch. complete := true. ^result
Yes. 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. "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
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
squeak-dev@lists.squeakfoundation.org