2014-06-23 22:50 GMT+02:00 Nicolas Cellier < [email protected]>:
> > > > 2014-06-23 22:38 GMT+02:00 Norbert Hartl <[email protected]>: > > Hmmm, >> >> I'm trying to write a test for it and I wonder why >> >> testDynamicVariableAccessFromDifferentProcess >> | process sem1 result | >> sem1 := Semaphore new. >> process := [ >> TestDynamicVariable >> value: 123 >> during: [ sem1 wait ] ] fork. >> Processor activeProcess >> evaluate: [ result := TestDynamicVariable value ] >> onBehalfOf: process. >> sem1 signal. >> self assert: result = 123 >> >> does not work. The variable accessing is in >> >> DynamicVariable>>#value: anObject during: aBlock >> | p oldValue | >> p := Processor activeProcess. >> oldValue := (p psValueAt: index) ifNil: [ self default ]. >> ^ [ >> p psValueAt: index put: anObject. >> aBlock value ] ensure: [ p psValueAt: index put: oldValue ] >> >> Any ideas? >> > > But what happens when you immediately fork, are you sure the forked > process immediately pre-empts the activeProcess? > What if you introduce Processor activeProcess yield after the fork? > > Ah, I just tried, it's Processor yield. [Transcript cr; show: 'A' ] fork. Processor yield. Transcript cr; show: 'B' . produces the required transcripting order. Without yielding, B comes before A. > >> > Norbert >> >> Am 23.06.2014 um 21:29 schrieb Eliot Miranda <[email protected]>: >> >> >> >> >> On Mon, Jun 23, 2014 at 12:05 PM, Norbert Hartl <[email protected]> >> wrote: >> >>> Hi Eliot, >>> >>> thank you very much. I imported your changes in a pharo 3 image and it >>> works awesome. So I'm preparing a slice for pharo. >>> >>> Thanks again, a very annoying problem seems to be solved, >>> >> >> glad to hear it, and thanks for your prompting me as it's now in Squeak >> trunk too. >> >> >>> >>> Norbert >>> >>> Am 23.06.2014 um 19:29 schrieb Eliot Miranda <[email protected]>: >>> >>> and here are the changes I've just committed to Squeak trunk. >>> >>> >>> On Mon, Jun 23, 2014 at 10:05 AM, Eliot Miranda<[email protected]> >>> wrote: >>> >>>> Hi Norbert, >>>> >>>> [ let me try again. never try and get code out too early in the >>>> morning ;-) ] >>>> >>>> it is the debugger that needs fixing, not your code !! :-). The >>>> debugger needs to respect process identity. Andreas and I (mostly Andreas) >>>> came up with the following changes at Qwaq. Your message is a good >>>> reminder that I need to add this to Squeak asap. >>>> >>>> The idea is for Process to have an additional inst var >>>> 'effectiveProcess' that holds the actual process running code. For the >>>> most part this is self, but in the debugger we substitute the process being >>>> debugged: >>>> >>>> *Process methods for accessing* >>>> *effectiveProcess* >>>> "effectiveProcess is a mechanism to allow process-faithful debugging. >>>> The debugger executes code >>>> on behalf of processes, so unless some effort is made the identity of >>>> Processor activeProcess is not >>>> correctly maintained when debugging code. The debugger uses >>>> evaluate:onBehalfOf: to assign the >>>> debugged process as the effectiveProcess of the process executing the >>>> code, preserving process >>>> identity." >>>> ^effectiveProcess ifNil: [self] >>>> >>>> then the relevant methods in Process and processorScheduler defer to >>>> effectiveProcess, e.g. >>>> >>>> *ProcessorScheduler methods for process state change* >>>> *terminateActive* >>>> "Terminate the process that is currently running." >>>> >>>> activeProcess effectiveProcess terminate >>>> >>>> and the debugging methods use evaluate:onBehalfOf: to install the >>>> process being debugged: >>>> >>>> *Process methods for private* >>>> *evaluate: aBlock onBehalfOf: aProcess* >>>> "Evaluate aBlock setting effectiveProcess to aProcess. Used >>>> in the execution simulation machinery to ensure that >>>> Processor activeProcess evaluates correctly when debugging." >>>> | oldEffectiveProcess | >>>> oldEffectiveProcess := effectiveProcess. >>>> effectiveProcess := aProcess. >>>> ^aBlock ensure: [effectiveProcess := oldEffectiveProcess] >>>> >>>> *Process methods for changing suspended state* >>>> *step* >>>> >>>> ^Processor activeProcess >>>> evaluate: [suspendedContext := suspendedContext step] >>>> onBehalfOf: self >>>> >>>> *stepToCallee* >>>> "Step until top context changes" >>>> >>>> Processor activeProcess >>>> evaluate: >>>> [| ctxt | >>>> ctxt := suspendedContext. >>>> [ctxt == suspendedContext] whileTrue: [ >>>> suspendedContext := suspendedContext step]] >>>> onBehalfOf: self. >>>> ^suspendedContext >>>> >>>> etc. Changes from a Qwaq image attached. >>>> >>>> HTH >>>> >>>> >>>> On Mon, Jun 23, 2014 at 4:50 AM, Norbert Hartl <[email protected]> >>>> wrote: >>>> >>>>> In my code I'm using a DynamicVariable to request a context object >>>>> when needed. Until now I knew the name DynamicVariable only from seaside. >>>>> There it is called WADynamicVariable and it is an exception. So I blindly >>>>> assumed the pharo DynamicVariable works the same. >>>>> I thought this might be a good optimization not to travel the stack >>>>> all the time but put in the process. >>>>> Now that I am using it I can see the difference. I find it real hard >>>>> using it because I don't know how to debug/step in code. DynamicVariable >>>>> is >>>>> a process specific variable but as soon as a debugger opens it is very >>>>> likely to be in another process. This makes stepping in method using the >>>>> DynamicVariable impossible. The only way round is to set break points >>>>> after >>>>> the dynamic lookup and step from there. But this feels just wrong. >>>>> What would be the best way to have DynamicVariable and be able to >>>>> debug anything? Or is there a variant that uses the stack instead of the >>>>> "active" process? >>>>> >>>>> thanks, >>>>> >>>>> Norbert >>>>> >>>>> >>>>> >>>> >>>> >>>> -- >>>> best, >>>> Eliot >>>> >>> >>> >>> >>> -- >>> best, >>> Eliot >>> <trunk4.6EffectiveProcessMethods.st >>> <http://trunk4.6effectiveprocessmethods.st/>> >>> >>> >>> >> >> >> -- >> best, >> Eliot >> >> >> >
