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
^[^ Jaromir
|
Hi
> On 13. Feb 2021, at 12:55, Jaromir <[hidden email]> 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 |
In reply to this post by Jaromir Matas
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
^[^ Jaromir
|
Free forum by Nabble | Edit this page |