[Pharo-project] serializing DynamicVariables (Zinc so far)
Guys...we are having a strange problem when exporting/importing Zinc. We have a problem when executing: executeRequestResponse self logRequest. ZnSignalProgress enabled ...... The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value. ZnSignalProgress is a subclass of DynamicVariable.... so I guess there is a black magic around this. There is a hook in Fuel where I can substitute an object being serialized for something else. Should I substitute DynamicVariables with something when serialized? send #value before serialize it? nil something? Thanks in advance, -- Mariano http://marianopeck.wordpress.com
anyone? On Wed, Aug 8, 2012 at 2:45 PM, Mariano Martinez Peck <marianopeck@gmail.com
wrote:
Guys...we are having a strange problem when exporting/importing Zinc. We have a problem when executing:
executeRequestResponse self logRequest. ZnSignalProgress enabled ......
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value. ZnSignalProgress is a subclass of DynamicVariable.... so I guess there is a black magic around this. There is a hook in Fuel where I can substitute an object being serialized for something else. Should I substitute DynamicVariables with something when serialized? send #value before serialize it? nil something?
Thanks in advance,
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
DynamicVariables aren't really dynamic, in the sense that they're not connected to the executing environment. In particular, their #value:during: behaviour is * store old value * run block * restore old value which means that if you do something tricky during the block - perhaps like serialising the current context - when you deserialise the block you _don't_ have the value of the dynamic variable as it was during serialising. That might or might not affect what you're seeing though. I hadn't spoken up earlier because I'm not sure what exactly goes on during exporting/importing Zinc. frank On 10 August 2012 11:16, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
anyone?
On Wed, Aug 8, 2012 at 2:45 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Guys...we are having a strange problem when exporting/importing Zinc. We have a problem when executing:
executeRequestResponse self logRequest. ZnSignalProgress enabled ......
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value. ZnSignalProgress is a subclass of DynamicVariable.... so I guess there is a black magic around this. There is a hook in Fuel where I can substitute an object being serialized for something else. Should I substitute DynamicVariables with something when serialized? send #value before serialize it? nil something?
Thanks in advance,
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
Mariano, This is the same problem that occurred when the first code using ZnSignalProgress was integrated in Pharo 2.0, it failed the first time only. I just can't remember how we got past this, I guess by a manual intervention by one of the integrators. I could also be that Sean committed something. Anyway, Zinc is just using existing infrastructure here. Sven On 08 Aug 2012, at 14:45, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Guys...we are having a strange problem when exporting/importing Zinc. We have a problem when executing:
executeRequestResponse self logRequest. ZnSignalProgress enabled ......
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value. ZnSignalProgress is a subclass of DynamicVariable.... so I guess there is a black magic around this. There is a hook in Fuel where I can substitute an object being serialized for something else. Should I substitute DynamicVariables with something when serialized? send #value before serialize it? nil something?
Thanks in advance,
-- Mariano http://marianopeck.wordpress.com
Sven Van Caekenberghe wrote
I could also be that Sean committed something.
I'll take a look tomorrow at the latest. If it's an emergency, I might be able to check later tonight... -- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image? Sean -- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help! On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com>wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0. Thanks! On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck < marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com>wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird. frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
The nil default is used as a 'not set' third value. ZnSignalProgress class>>#enabled "Answer if HTTPProgress should be signalled. The default is false." ^ self value ifNil: [ false ] ifNotNil: [ :value | value ] ZnClient>>#withProgressDo: block ^ ZnSignalProgress value ifNil: [ ZnSignalProgress value: self signalProgress during: [ ^ block value ] ] ifNotNil: [ block value ] ZnClient>>#signalProgress "Return true if I signal HTTPProgress notifications during execution." ^ self optionAt: #signalProgress ifAbsent: [ false ] Sven On 25 Aug 2012, at 12:50, Frank Shearar <frank.shearar@gmail.com> wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On Sat, 25 Aug 2012, Sven Van Caekenberghe wrote:
The nil default is used as a 'not set' third value.
ZnSignalProgress class>>#enabled "Answer if HTTPProgress should be signalled. The default is false."
^ self value ifNil: [ false ] ifNotNil: [ :value | value ]
ZnClient>>#withProgressDo: block ^ ZnSignalProgress value ifNil: [ ZnSignalProgress value: self signalProgress during: [ ^ block value ] ] ifNotNil: [ block value ]
DynamicVariables are stored in the env variable of Process, the stack doesn't store this information, so if you're about to serialize a state of a Process, then you have to serialize the env variable too, otherwise you'll lose information. Levente
ZnClient>>#signalProgress "Return true if I signal HTTPProgress notifications during execution."
^ self optionAt: #signalProgress ifAbsent: [ false ]
Sven
On 25 Aug 2012, at 12:50, Frank Shearar <frank.shearar@gmail.com> wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On 25 August 2012 14:30, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 25 Aug 2012, Sven Van Caekenberghe wrote:
The nil default is used as a 'not set' third value.
ZnSignalProgress class>>#enabled "Answer if HTTPProgress should be signalled. The default is false."
^ self value ifNil: [ false ] ifNotNil: [ :value | value ]
ZnClient>>#withProgressDo: block ^ ZnSignalProgress value ifNil: [ ZnSignalProgress value: self signalProgress during: [ ^ block value ] ] ifNotNil: [ block value ]
DynamicVariables are stored in the env variable of Process, the stack doesn't store this information, so if you're about to serialize a state of a Process, then you have to serialize the env variable too, otherwise you'll lose information.
I'm sure that's what I said in my initial response to Mariano's question :) Yes, indeed, that is precisely the problem with DynamicVariable. (Scala's and Clojure's dynamic variables suffer the same problem.) That's why these guys don't play well with stack slicing & dicing (http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express...). Handily, http://ss3.gemstone.com/ss/Control _does_ do this - keep the information on the stack, that is. Look at the DelimitedDynamicVariable tests in that package. frank
Levente
ZnClient>>#signalProgress "Return true if I signal HTTPProgress notifications during execution."
^ self optionAt: #signalProgress ifAbsent: [ false ]
Sven
On 25 Aug 2012, at 12:50, Frank Shearar <frank.shearar@gmail.com> wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context:
http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On Sat, 25 Aug 2012, Frank Shearar wrote:
On 25 August 2012 14:30, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 25 Aug 2012, Sven Van Caekenberghe wrote:
The nil default is used as a 'not set' third value.
ZnSignalProgress class>>#enabled "Answer if HTTPProgress should be signalled. The default is false."
^ self value ifNil: [ false ] ifNotNil: [ :value | value ]
ZnClient>>#withProgressDo: block ^ ZnSignalProgress value ifNil: [ ZnSignalProgress value: self signalProgress during: [ ^ block value ] ] ifNotNil: [ block value ]
DynamicVariables are stored in the env variable of Process, the stack doesn't store this information, so if you're about to serialize a state of a Process, then you have to serialize the env variable too, otherwise you'll lose information.
I'm sure that's what I said in my initial response to Mariano's question :) Yes, indeed, that is precisely the problem with DynamicVariable. (Scala's and Clojure's dynamic variables suffer the same problem.) That's why these guys don't play well with stack slicing & dicing (http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express...).
Handily, http://ss3.gemstone.com/ss/Control _does_ do this - keep the information on the stack, that is. Look at the DelimitedDynamicVariable tests in that package.
Yeah, right, but it lacks the performance advantage of DynamicVariable over Exceptions. I don't think it's too much hassle to serialize the variables of the Process besides the stack (sometimes you just can't avoid it), but if you think it is, then a mixed system is the best solution: - store the value both in the process and on the stack - start the lookup in the process first, if the variable is not found there, then continue on the stack and store the result in the process before returning it, so it will be found next time there Levente
frank
Levente
ZnClient>>#signalProgress "Return true if I signal HTTPProgress notifications during execution."
^ self optionAt: #signalProgress ifAbsent: [ false ]
Sven
On 25 Aug 2012, at 12:50, Frank Shearar <frank.shearar@gmail.com> wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context:
http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On 25 August 2012 22:34, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 25 Aug 2012, Frank Shearar wrote:
On 25 August 2012 14:30, Levente Uzonyi <leves@elte.hu> wrote:
On Sat, 25 Aug 2012, Sven Van Caekenberghe wrote:
The nil default is used as a 'not set' third value.
ZnSignalProgress class>>#enabled "Answer if HTTPProgress should be signalled. The default is false."
^ self value ifNil: [ false ] ifNotNil: [ :value | value ]
ZnClient>>#withProgressDo: block ^ ZnSignalProgress value ifNil: [ ZnSignalProgress value: self signalProgress during: [ ^ block value ] ] ifNotNil: [ block value ]
DynamicVariables are stored in the env variable of Process, the stack doesn't store this information, so if you're about to serialize a state of a Process, then you have to serialize the env variable too, otherwise you'll lose information.
I'm sure that's what I said in my initial response to Mariano's question :) Yes, indeed, that is precisely the problem with DynamicVariable. (Scala's and Clojure's dynamic variables suffer the same problem.) That's why these guys don't play well with stack slicing & dicing
(http://www.lshift.net/blog/2012/06/27/resumable-exceptions-can-macro-express...).
Handily, http://ss3.gemstone.com/ss/Control _does_ do this - keep the information on the stack, that is. Look at the DelimitedDynamicVariable tests in that package.
Yeah, right, but it lacks the performance advantage of DynamicVariable over Exceptions.
Sure: every time you want to evaluate the delimited dynvar you have to walk the stack up to the last set value. The solution to that would be to hack Contexts to support the dynamic environment, but that would be rather more drastic. The choices thus become, if you want sensible behaviour with general stack hacking: * have DynamicVariables that have broken behaviour when you do any kind of stack manipulations (and they cannot be fixed: implement them differently and you'll simply have _different_ broken behaviour) * take the performance hit and use DelimitedDynamicVariables as they are * spend ages hacking the image/VM to support dynamic environments directly, instead of using resumable exceptions. (Essentially you'd need to extend a Context to have a Dictionary (or similar) containing the dynamic environment. Touching Context means - as far as I understand things, at least - touching the VM because the VM knows a whole lot about Contexts.) frank
I don't think it's too much hassle to serialize the variables of the Process besides the stack (sometimes you just can't avoid it), but if you think it is, then a mixed system is the best solution: - store the value both in the process and on the stack - start the lookup in the process first, if the variable is not found there, then continue on the stack and store the result in the process before returning it, so it will be found next time there
That sounds like a reasonable workaround to address Mariano's immediate problem :) frank
Levente
frank
Levente
ZnClient>>#signalProgress "Return true if I signal HTTPProgress notifications during execution."
^ self optionAt: #signalProgress ifAbsent: [ false ]
Sven
On 25 Aug 2012, at 12:50, Frank Shearar <frank.shearar@gmail.com> wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context:
http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On Sun, 26 Aug 2012, Frank Shearar wrote:
That sounds like a reasonable workaround to address Mariano's immediate problem :)
I don't see what other issues are there to solve. :) Anyway, here's a highly untested example of what I had in my mind: http://leves.web.elte.hu/squeak/StackSerializableDynamicVariable.st Is uses a method in Process which is not present in current images: environmentAt: key ifAbsentPut: aBlock ^(env ifNil: [ env := Dictionary new ]) at: key ifAbsentPut: aBlock. Levente
On 26 August 2012 17:55, Levente Uzonyi <leves@elte.hu> wrote:
On Sun, 26 Aug 2012, Frank Shearar wrote:
That sounds like a reasonable workaround to address Mariano's immediate problem :)
I don't see what other issues are there to solve. :)
Then you should go reread my article, and the articles it references :) Both have examples of how undelimited dynamic variables don't work sensibly with delimited continuations. Kiselyov goes further and shows how they _cannot_ work sensibly. Serialising a running process implicitly creates a delimited continuation. Ergo, Fun Times! frank
Anyway, here's a highly untested example of what I had in my mind: http://leves.web.elte.hu/squeak/StackSerializableDynamicVariable.st
Yep, using resumable exceptions to implement delimited dynamic variables. That's exactly what Control does, only without DynamicVariable necessarily polluting the global namespace.
Is uses a method in Process which is not present in current images:
environmentAt: key ifAbsentPut: aBlock
^(env ifNil: [ env := Dictionary new ]) at: key ifAbsentPut: aBlock.
Current _Pharo_ images, maybe. I'm pretty sure I looked at a trunk image with it in the last few hours (but obviously am too lazy to actually go check :/) frank
Levente
On Sun, 26 Aug 2012, Frank Shearar wrote:
On 26 August 2012 17:55, Levente Uzonyi <leves@elte.hu> wrote:
On Sun, 26 Aug 2012, Frank Shearar wrote:
That sounds like a reasonable workaround to address Mariano's immediate problem :)
I don't see what other issues are there to solve. :)
Then you should go reread my article, and the articles it references :) Both have examples of how undelimited dynamic variables don't work sensibly with delimited continuations. Kiselyov goes further and shows how they _cannot_ work sensibly.
I took a look why DynamicVariable doesn't work with Control and I found that the reason is that Control doesn't play well with #ensure:. Let's see it in this example: DynamicVariable value: 1 during: [ [ DynamicVariable value: 2 during: [ [ :k | DynamicVariable value ] shift ]] reset ] When #reset is sent, the value of the variable is 1, then it starts evaluating the receiver block. The value is set to 2 and then #shift occurs. #shift cuts the stack back, so the argument of #ensure:, which would restore the value of the variable in the process' environment to 1 is never evaluated. So Control breaks the contract of #ensure:, because it starts the evaluation of its receiver, but doesn't evaluate its argument: x := 0. [ [ x := 1. [ :k | x ] shift ] ensure: [ x := 2 ] ] reset. "==> 1"
Serialising a running process implicitly creates a delimited continuation. Ergo, Fun Times!
frank
Anyway, here's a highly untested example of what I had in my mind: http://leves.web.elte.hu/squeak/StackSerializableDynamicVariable.st
Yep, using resumable exceptions to implement delimited dynamic variables. That's exactly what Control does, only without DynamicVariable necessarily polluting the global namespace.
The most common use case of DynamicVariable involves accessing the variable from "unrelated" places. Using the global namespace is an easy way to avoid passing the variable around all the time. It's basically the same as subclassing Notification (which is a common practice - a pattern - to implement dynamic variables) from this POV.
Is uses a method in Process which is not present in current images:
environmentAt: key ifAbsentPut: aBlock
^(env ifNil: [ env := Dictionary new ]) at: key ifAbsentPut: aBlock.
Current _Pharo_ images, maybe. I'm pretty sure I looked at a trunk image with it in the last few hours (but obviously am too lazy to actually go check :/)
I just wrote this method, so I'm pretty sure it's not present in any image. :) Levente
frank
Levente
On 27 August 2012 12:16, Levente Uzonyi <leves@elte.hu> wrote:
On Sun, 26 Aug 2012, Frank Shearar wrote:
On 26 August 2012 17:55, Levente Uzonyi <leves@elte.hu> wrote:
On Sun, 26 Aug 2012, Frank Shearar wrote:
That sounds like a reasonable workaround to address Mariano's immediate problem :)
I don't see what other issues are there to solve. :)
Then you should go reread my article, and the articles it references :) Both have examples of how undelimited dynamic variables don't work sensibly with delimited continuations. Kiselyov goes further and shows how they _cannot_ work sensibly.
I took a look why DynamicVariable doesn't work with Control and I found that the reason is that Control doesn't play well with #ensure:. Let's see it in this example:
DynamicVariable value: 1 during: [ [ DynamicVariable value: 2 during: [ [ :k | DynamicVariable value ] shift ]] reset ]
When #reset is sent, the value of the variable is 1, then it starts evaluating the receiver block. The value is set to 2 and then #shift occurs. #shift cuts the stack back, so the argument of #ensure:, which would restore the value of the variable in the process' environment to 1 is never evaluated.
So Control breaks the contract of #ensure:, because it starts the evaluation of its receiver, but doesn't evaluate its argument:
The shift looks like it cuts out that part of the stack responsible for setting the DynamicVariable to 2. In fact, rather, it DOES cut it out. The problem is that the value's not stored on the stack, so the stack cutting doesn't behave as it should. So you have a well-implemented dynamic variable, and a well-implemented delimited continuation, and yet when you add them together you get broken behaviour. My point is that you _cannot_ have undelimited dynamic variables and delimited continuations behaving well together. Hence, if you're slicing stacks, you _cannot_ just use dynamic variables because they will not behave as they should. If you need a dynamic variable when slicing a stack, you need to use a delimited dynamic variable, which _will_ behave sensibly. Other than claims of higher performance (which would probably require VM changes to remove the need for all the stack-walking caused by the resumable exceptions), there's really no reason to choose undelimited dynamic variables: they're as expressive, but can't be combined with delimited continuations. And you want delimited continuations because undelimited continuations (call/cc and friends) not only suck but suck _hard_. Oh, and of course we have continuations whether we like them or not - thisContext. (In fact a fork is a delimited continuation.) frank
x := 0. [ [ x := 1. [ :k | x ] shift ] ensure: [ x := 2 ] ] reset. "==> 1"
Serialising a running process implicitly creates a delimited continuation. Ergo, Fun Times!
frank
Anyway, here's a highly untested example of what I had in my mind: http://leves.web.elte.hu/squeak/StackSerializableDynamicVariable.st
Yep, using resumable exceptions to implement delimited dynamic variables. That's exactly what Control does, only without DynamicVariable necessarily polluting the global namespace.
The most common use case of DynamicVariable involves accessing the variable from "unrelated" places. Using the global namespace is an easy way to avoid passing the variable around all the time. It's basically the same as subclassing Notification (which is a common practice - a pattern - to implement dynamic variables) from this POV.
Is uses a method in Process which is not present in current images:
environmentAt: key ifAbsentPut: aBlock
^(env ifNil: [ env := Dictionary new ]) at: key ifAbsentPut: aBlock.
Current _Pharo_ images, maybe. I'm pretty sure I looked at a trunk image with it in the last few hours (but obviously am too lazy to actually go check :/)
I just wrote this method, so I'm pretty sure it's not present in any image. :)
Levente
frank
Levente
frank would you be interested to write a chapter on dynamicVariable and delimited one? Because it would be really good to be able to read that. On Aug 25, 2012, at 12:50 PM, Frank Shearar wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
On 25 August 2012 20:19, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
frank would you be interested to write a chapter on dynamicVariable and delimited one? Because it would be really good to be able to read that.
I would, but I'll only have time for it next month or later. I need to write decent documentation for the library anyway, so I could always solve both issues in one go. frank
On Aug 25, 2012, at 12:50 PM, Frank Shearar wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
we are not in hurry :) On Aug 26, 2012, at 4:25 PM, Frank Shearar wrote:
On 25 August 2012 20:19, Stéphane Ducasse <stephane.ducasse@inria.fr> wrote:
frank would you be interested to write a chapter on dynamicVariable and delimited one? Because it would be really good to be able to read that.
I would, but I'll only have time for it next month or later. I need to write decent documentation for the library anyway, so I could always solve both issues in one go.
frank
On Aug 25, 2012, at 12:50 PM, Frank Shearar wrote:
On 25 August 2012 09:31, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Sean. I am still seing the problem :( It is difficult to make it YOU to reproduce it, but it is easy that tomorrow I show it to you :) Basically, what is happening is that
ZnClient >> executeRequestResponse self logRequest. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Writing request' ]. request writeOn: connection. connection flush. ZnSignalProgress enabled ifTrue: [ HTTPProgress signal: 'Reading response' ]. response := request method = #HEAD ifTrue: [ ZnResponse readHeaderFrom: connection ] ifFalse: [ self streaming ifTrue: [ ZnResponse readStreamingFrom: connection ] ifFalse: [ ZnResponse readFrom: connection ] ]. self logResponse
throws a mustBeBoolean in the first line "ZnSignalProgress enabled ". It seems that such expression answered the SmallINteger 30 the first time. If I take the debugger and I evaluate ZnSignalProgress enabled again, it answers me false, which is the correct value. Ahh yes, this in latest 2.0.
I would have expected a ZnSignalProgress class >> default saying "^ true" (or something else of a Boolean nature). DynamicVariables have a default value of nil unless otherwise set. Or, since you're getting a value of 30, something somewhere is saying ZnSignalProgress value: 30 during: ["something"]... which would be very weird.
frank
Thanks!
On Fri, Aug 17, 2012 at 10:32 PM, Mariano Martinez Peck <marianopeck@gmail.com> wrote:
Hi Frank and Sean. The problem was quite hard to reproduce. You need to rebuild a Pharo image from a kernel using Tanker ;) Anyway, since we are changing completely Tanker now it may have been solved. I did a quick test (of a similar case) and it works. So once I have the example of the kernel again I will trying again. Thanks for offering the help!
On Fri, Aug 17, 2012 at 2:33 PM, Sean P. DeNigris <sean@clipperadams.com> wrote:
Mariano Martinez Peck wrote
The first time, #enable answers something wrong. The second time it is called, it seems to answer the correct value.
Mariano, would you give some more details about the wrong value, the expected value, and the steps to reproduce? I took a look but I'm not seeing what the problem is... b.t.w. is this a 1.4 or 2.0 image?
Sean
-- View this message in context: http://forum.world.st/serializing-DynamicVariables-Zinc-so-far-tp4643514p464... Sent from the Pharo Smalltalk mailing list archive at Nabble.com.
-- Mariano http://marianopeck.wordpress.com
-- Mariano http://marianopeck.wordpress.com
participants (6)
-
Frank Shearar -
Levente Uzonyi -
Mariano Martinez Peck -
Sean P. DeNigris -
Stéphane Ducasse -
Sven Van Caekenberghe