Hi,
After testing the different approaches I decided to use TimedPromises for my problem. But I overrided the method value, because it uses recursions, if the signalTimeout-exception was resumed. This is an ugly design, because you cannot know the recursion depth. In my program, every 10 seconds such an exception is thrown and resumed. Sometimes, it lasts for days until the value is computated, so you can imagine, how many recursions are stored on the stack. I redesigned the method as follows: TimedPromise>>value [| hasResult | delay wait. "Wait for data arrival or alarm expiry." hasResult := delay inProgress. delay disable. sync signal. "To allow multiple reads of the result" exception == nil ifTrue: [hasResult ifTrue: [^value] ifFalse: [self signalTimeout. "If resumed, start over" sync wait "Undo the signal above"]] ifFalse: [^exception clearForReraise; searchFrom: thisContext; raise]] repeat Maybe someone from Cincom uses this change for the next release :-). Greeting Klaus Mülheims Collogia AG Ubierring 11 50678 Köln Germany +49 221 336080 http://www.collogia.de -----Ursprüngliche Nachricht----- Von: Mülheims, Klaus [mailto:[hidden email]] Gesendet: Montag, 4. September 2006 17:16 An: vwnc-list Betreff: Semaphors with timeouts Hi, I need a kind of Semaphore that waits only a predefined timeout, something like: sem := Semaphore new. gotSem := sem waitMaxTime: 45. This methods returns true if a could enter the critical section. But if I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter the critical section in this time, the method returns false and i can react on this timeout. Has anybody seen such a behaviour in VisualWorks? Greetings Klasu Muelheims Collogia AG Ubierring 11 50678 Köln Germany +49 221 336080 http://www.collogia.de Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt. Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt. |
Klaus
TimedPromise solves some problems elegantly. However there is a major annoyance with them- When something goes wrong it is not possible to debug the code inside the promise block. To see this evaluate the following: promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript show: 'bar'] timedPromiseFor: 10000. promise value. The debugger is positioned at the value send and it is not possible to get into the block. In the example above you can at least see the source but if the block is created in another method then you don't even get that. This is broken up to and including 7.4.1. Now if 'asdasd' /3. is replaced with self halt. The debugger does work work correctly so I imagine it should be possible to fix this. Joerg > -----Original Message----- > From: Mülheims, Klaus [mailto:[hidden email]] > Sent: September 12, 2006 1:53 AM > To: vwnc-list > Subject: AW: Semaphors with timeouts > > Hi, > > After testing the different approaches I decided to use TimedPromises for > my problem. > But I overrided the method value, because it uses recursions, if the > signalTimeout-exception was resumed. This is an ugly design, because you > cannot know the recursion depth. In my program, every 10 seconds such an > exception is thrown and resumed. Sometimes, it lasts for days until the > value is computated, so you can imagine, how many recursions are stored on > the stack. > I redesigned the method as follows: > > TimedPromise>>value > [| hasResult | > delay wait. "Wait for data arrival or alarm expiry." > hasResult := delay inProgress. > delay disable. > sync signal. "To allow multiple reads of the result" > exception == nil > ifTrue: > [hasResult > ifTrue: [^value] > ifFalse: > [self signalTimeout. > "If resumed, start over" > sync wait "Undo the signal above"]] > ifFalse: > [^exception > clearForReraise; > searchFrom: thisContext; > raise]] > repeat > > Maybe someone from Cincom uses this change for the next release :-). > > Greeting > > Klaus Mülheims > > Collogia AG > Ubierring 11 > > 50678 Köln > Germany > +49 221 336080 > http://www.collogia.de > > -----Ursprüngliche Nachricht----- > Von: Mülheims, Klaus [mailto:[hidden email]] > Gesendet: Montag, 4. September 2006 17:16 > An: vwnc-list > Betreff: Semaphors with timeouts > > Hi, > > I need a kind of Semaphore that waits only a predefined timeout, something > like: > sem := Semaphore new. > gotSem := sem waitMaxTime: 45. > > This methods returns true if a could enter the critical section. But if > I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter > the critical section in this time, the method returns false and i can > react on this timeout. > > Has anybody seen such a behaviour in VisualWorks? > > Greetings > > Klasu Muelheims > > > Collogia AG > Ubierring 11 > > 50678 Köln > Germany > +49 221 336080 > http://www.collogia.de > > > Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte > Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren > oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E- > Mails übernehmen wir keine Haftung für den Inhalt. > > > Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte > Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren > oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E- > Mails übernehmen wir keine Haftung für den Inhalt. |
Joerg Beekmann wrote:
> TimedPromise solves some problems elegantly. However there is a major > annoyance with them- When something goes wrong it is not possible to > debug the code inside the promise block. To see this evaluate the > following: > > promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript > show: 'bar'] timedPromiseFor: 10000. promise value. > > The debugger is positioned at the value send and it is not possible > to get into the block. In the example above you can at least see the > source but if the block is created in another method then you don't > even get that. This is broken up to and including 7.4.1. > > Now if 'asdasd' /3. is replaced with self halt. The debugger does > work work correctly so I imagine it should be possible to fix this. What would you expect the fixed behavior to be? The only thing I can imagine is modifying the debugger so that when you step into timedPromiseFor:, it would open another debugger for the process that runs the block. That way you could step through both processes any way you want. The same argument could probably be made for any code that forks or creates a new process. However I'm not sure how practical that would end up being. It may well be that putting a breakpoint at the exact place you want a debugger to open would often be a more efficient approach anyway. I find that when debugging a problem involving multiple processes decent logging is the best tool to pin point the place to look at and then put a breakpoint there. Martin |
Hello Martin
I am not expecting to be able to step into a timed promise, I just want to be able to debug an exception that arrises within the promise block. You comparison to just a normally forked block is helpful. In a workspace do the following to initialize the variable aBlock: aBlock := [Transcript show: 'start';cr. 'asdasd' /3. Transcript show: 'bar']. Then try the following: aBlock fork. As you would expect how you can debug the exception that is raised within the block. Now try the following: (aBlock timedPromiseFor: 10000) value In this case there is no information about the excepion or its context. Joerg > -----Original Message----- > From: Martin Kobetic [mailto:[hidden email]] > Sent: September 18, 2006 9:33 AM > To: Joerg Beekmann > Cc: vwnc-list > Subject: Re: TimedPromise can't be debugged easily - WAS: > Semaphors with timeouts > > Joerg Beekmann wrote: > > TimedPromise solves some problems elegantly. However there > is a major > > annoyance with them- When something goes wrong it is not > possible to > > debug the code inside the promise block. To see this evaluate the > > following: > > > > promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript > > show: 'bar'] timedPromiseFor: 10000. promise value. > > > > The debugger is positioned at the value send and it is not > possible to > > get into the block. In the example above you can at least see the > > source but if the block is created in another method then you don't > > even get that. This is broken up to and including 7.4.1. > > > > Now if 'asdasd' /3. is replaced with self halt. The > debugger does work > > work correctly so I imagine it should be possible to fix this. > > What would you expect the fixed behavior to be? The only > thing I can imagine is modifying the debugger so that when > you step into timedPromiseFor:, it would open another > debugger for the process that runs the block. That way you > could step through both processes any way you want. The same > argument could probably be made for any code that forks or > creates a new process. However I'm not sure how practical > that would end up being. It may well be that putting a > breakpoint at the exact place you want a debugger to open > would often be a more efficient approach anyway. I find that > when debugging a problem involving multiple processes decent > logging is the best tool to pin point the place to look at > and then put a breakpoint there. > > Martin > |
Hi Joerg,
OK, I see. It seems that we have conflicting requirements then. Basically you don't want Errors in the promise block to be handled (See BlockClosure>>promiseBlock:). However while that might be handy for debugging, it makes things more difficult for runtime. Currently any errors will be captured and injected into the calling process through the promise. They will be resignaled there, so the caller can use normal exception handling to react to the problems. Otherwise you'll just have notifiers popping up from the background thread with no chance to intervene. It's true that the resignaled exception won't have the original context where it was created, since that process is long gone by then, but you have all the other information there. I'm not sure how to resolve this. You can have a subclass of Promise that would behave one way or the other based on some global switch, but it may become unmanageable with heavy use of promises. An instance based flag is usually a pain to work with though. I'm afraid you'll have to pick your poison here. Martin Joerg Beekmann wrote: > Hello Martin > > I am not expecting to be able to step into a timed promise, I just want > to be able to debug an exception that arrises within the promise block. > You comparison to just a normally forked block is helpful. In a > workspace do the following to initialize the variable aBlock: > > aBlock := [Transcript show: 'start';cr. > 'asdasd' /3. > Transcript show: 'bar']. > > Then try the following: > > aBlock fork. > > As you would expect how you can debug the exception that is raised > within the block. > > Now try the following: > > (aBlock timedPromiseFor: 10000) value > > In this case there is no information about the excepion or its context. > > Joerg > > > >>-----Original Message----- >>From: Martin Kobetic [mailto:[hidden email]] >>Sent: September 18, 2006 9:33 AM >>To: Joerg Beekmann >>Cc: vwnc-list >>Subject: Re: TimedPromise can't be debugged easily - WAS: >>Semaphors with timeouts >> >>Joerg Beekmann wrote: >> >>>TimedPromise solves some problems elegantly. However there >> >>is a major >> >>>annoyance with them- When something goes wrong it is not >> >>possible to >> >>>debug the code inside the promise block. To see this evaluate the >>>following: >>> >>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript >>>show: 'bar'] timedPromiseFor: 10000. promise value. >>> >>>The debugger is positioned at the value send and it is not >> >>possible to >> >>>get into the block. In the example above you can at least see the >>>source but if the block is created in another method then you don't >>>even get that. This is broken up to and including 7.4.1. >>> >>>Now if 'asdasd' /3. is replaced with self halt. The >> >>debugger does work >> >>>work correctly so I imagine it should be possible to fix this. >> >>What would you expect the fixed behavior to be? The only >>thing I can imagine is modifying the debugger so that when >>you step into timedPromiseFor:, it would open another >>debugger for the process that runs the block. That way you >>could step through both processes any way you want. The same >>argument could probably be made for any code that forks or >>creates a new process. However I'm not sure how practical >>that would end up being. It may well be that putting a >>breakpoint at the exact place you want a debugger to open >>would often be a more efficient approach anyway. I find that >>when debugging a problem involving multiple processes decent >>logging is the best tool to pin point the place to look at >>and then put a breakpoint there. >> >>Martin >> > > |
Hi Martin
Humm I see the issue. At first I thought the promise process could just block and one could then user the ProcessManager to debug it, but in that case the promise will not return so that's no good. > is long gone by then, but you have all the other information there. Well, more information would definitly help. What about capturing a stack trace or even a portion of one. Joerg > -----Original Message----- > From: Martin Kobetic [mailto:[hidden email]] > Hi Joerg, > > OK, I see. It seems that we have conflicting requirements then. > Basically you don't want Errors in the promise block to be > handled (See > BlockClosure>>promiseBlock:). However while that might be handy for > debugging, it makes things more difficult for runtime. > Currently any errors will be captured and injected into the > calling process through the promise. They will be resignaled > there, so the caller can use normal exception handling to > react to the problems. Otherwise you'll just have notifiers > popping up from the background thread with no chance to > intervene. It's true that the resignaled exception won't have > the original context where it was created, since that process > is long gone by then, but you have all the other information there. > > I'm not sure how to resolve this. You can have a subclass of > Promise that would behave one way or the other based on some > global switch, but it may become unmanageable with heavy use > of promises. An instance based flag is usually a pain to work > with though. I'm afraid you'll have to pick your poison here. > > Martin > > Joerg Beekmann wrote: > > > Hello Martin > > > > I am not expecting to be able to step into a timed promise, I just > > want to be able to debug an exception that arrises within > the promise block. > > You comparison to just a normally forked block is helpful. In a > > workspace do the following to initialize the variable aBlock: > > > > aBlock := [Transcript show: 'start';cr. > > 'asdasd' /3. > > Transcript show: 'bar']. > > > > Then try the following: > > > > aBlock fork. > > > > As you would expect how you can debug the exception that is raised > > within the block. > > > > Now try the following: > > > > (aBlock timedPromiseFor: 10000) value > > > > In this case there is no information about the excepion or > its context. > > > > Joerg > > > > > > > >>-----Original Message----- > >>From: Martin Kobetic [mailto:[hidden email]] > >>Sent: September 18, 2006 9:33 AM > >>To: Joerg Beekmann > >>Cc: vwnc-list > >>Subject: Re: TimedPromise can't be debugged easily - WAS: > >>Semaphors with timeouts > >> > >>Joerg Beekmann wrote: > >> > >>>TimedPromise solves some problems elegantly. However there > >> > >>is a major > >> > >>>annoyance with them- When something goes wrong it is not > >> > >>possible to > >> > >>>debug the code inside the promise block. To see this evaluate the > >>>following: > >>> > >>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript > >>>show: 'bar'] timedPromiseFor: 10000. promise value. > >>> > >>>The debugger is positioned at the value send and it is not > >> > >>possible to > >> > >>>get into the block. In the example above you can at least see the > >>>source but if the block is created in another method then > you don't > >>>even get that. This is broken up to and including 7.4.1. > >>> > >>>Now if 'asdasd' /3. is replaced with self halt. The > >> > >>debugger does work > >> > >>>work correctly so I imagine it should be possible to fix this. > >> > >>What would you expect the fixed behavior to be? The only > thing I can > >>imagine is modifying the debugger so that when you step into > >>timedPromiseFor:, it would open another debugger for the > process that > >>runs the block. That way you could step through both > processes any way > >>you want. The same argument could probably be made for any > code that > >>forks or creates a new process. However I'm not sure how practical > >>that would end up being. It may well be that putting a > breakpoint at > >>the exact place you want a debugger to open would often be a more > >>efficient approach anyway. I find that when debugging a problem > >>involving multiple processes decent logging is the best tool to pin > >>point the place to look at and then put a breakpoint there. > >> > >>Martin > >> > > > > > > |
Joerg
I don't get it, why not put a breakpoint in BlockClosure>>promiseBlock:? Terry =========================================================== Terry Raymond Smalltalk Professional Debug Package Crafted Smalltalk 80 Lazywood Ln. Tiverton, RI 02878 (401) 624-4517 [hidden email] <http://www.craftedsmalltalk.com> =========================================================== > -----Original Message----- > From: Joerg Beekmann [mailto:[hidden email]] > Sent: Tuesday, September 19, 2006 2:09 PM > To: Martin Kobetic > Cc: vwnc-list > Subject: RE: TimedPromise can't be debugged easily > > Hi Martin > > Humm I see the issue. At first I thought the promise process could just > block and one could then user the ProcessManager to debug it, but in > that case the promise will not return so that's no good. > > > is long gone by then, but you have all the other information there. > > Well, more information would definitly help. What about capturing a > stack trace or even a portion of one. > > > Joerg > > > -----Original Message----- > > From: Martin Kobetic [mailto:[hidden email]] > > Hi Joerg, > > > > OK, I see. It seems that we have conflicting requirements then. > > Basically you don't want Errors in the promise block to be > > handled (See > > BlockClosure>>promiseBlock:). However while that might be handy for > > debugging, it makes things more difficult for runtime. > > Currently any errors will be captured and injected into the > > calling process through the promise. They will be resignaled > > there, so the caller can use normal exception handling to > > react to the problems. Otherwise you'll just have notifiers > > popping up from the background thread with no chance to > > intervene. It's true that the resignaled exception won't have > > the original context where it was created, since that process > > is long gone by then, but you have all the other information there. > > > > I'm not sure how to resolve this. You can have a subclass of > > Promise that would behave one way or the other based on some > > global switch, but it may become unmanageable with heavy use > > of promises. An instance based flag is usually a pain to work > > with though. I'm afraid you'll have to pick your poison here. > > > > Martin > > > > Joerg Beekmann wrote: > > > > > Hello Martin > > > > > > I am not expecting to be able to step into a timed promise, I just > > > want to be able to debug an exception that arrises within > > the promise block. > > > You comparison to just a normally forked block is helpful. In a > > > workspace do the following to initialize the variable aBlock: > > > > > > aBlock := [Transcript show: 'start';cr. > > > 'asdasd' /3. > > > Transcript show: 'bar']. > > > > > > Then try the following: > > > > > > aBlock fork. > > > > > > As you would expect how you can debug the exception that is raised > > > within the block. > > > > > > Now try the following: > > > > > > (aBlock timedPromiseFor: 10000) value > > > > > > In this case there is no information about the excepion or > > its context. > > > > > > Joerg > > > > > > > > > > > >>-----Original Message----- > > >>From: Martin Kobetic [mailto:[hidden email]] > > >>Sent: September 18, 2006 9:33 AM > > >>To: Joerg Beekmann > > >>Cc: vwnc-list > > >>Subject: Re: TimedPromise can't be debugged easily - WAS: > > >>Semaphors with timeouts > > >> > > >>Joerg Beekmann wrote: > > >> > > >>>TimedPromise solves some problems elegantly. However there > > >> > > >>is a major > > >> > > >>>annoyance with them- When something goes wrong it is not > > >> > > >>possible to > > >> > > >>>debug the code inside the promise block. To see this evaluate the > > >>>following: > > >>> > > >>>promise := [Transcript show: 'start';cr. 'asdasd' /3. Transcript > > >>>show: 'bar'] timedPromiseFor: 10000. promise value. > > >>> > > >>>The debugger is positioned at the value send and it is not > > >> > > >>possible to > > >> > > >>>get into the block. In the example above you can at least see the > > >>>source but if the block is created in another method then > > you don't > > >>>even get that. This is broken up to and including 7.4.1. > > >>> > > >>>Now if 'asdasd' /3. is replaced with self halt. The > > >> > > >>debugger does work > > >> > > >>>work correctly so I imagine it should be possible to fix this. > > >> > > >>What would you expect the fixed behavior to be? The only > > thing I can > > >>imagine is modifying the debugger so that when you step into > > >>timedPromiseFor:, it would open another debugger for the > > process that > > >>runs the block. That way you could step through both > > processes any way > > >>you want. The same argument could probably be made for any > > code that > > >>forks or creates a new process. However I'm not sure how practical > > >>that would end up being. It may well be that putting a > > breakpoint at > > >>the exact place you want a debugger to open would often be a more > > >>efficient approach anyway. I find that when debugging a problem > > >>involving multiple processes decent logging is the best tool to pin > > >>point the place to look at and then put a breakpoint there. > > >> > > >>Martin > > >> > > > > > > > > > > |
In reply to this post by Mülheims, Klaus
Sorry about a late response, but I hope better late then never in this
case. I created AR#51276: "Resuming a PromiseExpiredError entails a recursive call, can we avoid that ?" for your proposal and we will consider it. Thanks, Martin Mülheims wrote: > Hi, > > After testing the different approaches I decided to use TimedPromises for my problem. > But I overrided the method value, because it uses recursions, if the signalTimeout-exception was resumed. This is an ugly design, because you cannot know the recursion depth. In my program, every 10 seconds such an exception is thrown and resumed. Sometimes, it lasts for days until the value is computated, so you can imagine, how many recursions are stored on the stack. > I redesigned the method as follows: > > TimedPromise>>value > [| hasResult | > delay wait. "Wait for data arrival or alarm expiry." > hasResult := delay inProgress. > delay disable. > sync signal. "To allow multiple reads of the result" > exception == nil > ifTrue: > [hasResult > ifTrue: [^value] > ifFalse: > [self signalTimeout. > "If resumed, start over" > sync wait "Undo the signal above"]] > ifFalse: > [^exception > clearForReraise; > searchFrom: thisContext; > raise]] > repeat > > Maybe someone from Cincom uses this change for the next release :-). > > Greeting > > Klaus Mülheims > > Collogia AG > Ubierring 11 > > 50678 Köln > Germany > +49 221 336080 > http://www.collogia.de > > -----Ursprüngliche Nachricht----- > Von: Mülheims, Klaus [mailto:[hidden email]] > Gesendet: Montag, 4. September 2006 17:16 > An: vwnc-list > Betreff: Semaphors with timeouts > > Hi, > > I need a kind of Semaphore that waits only a predefined timeout, something like: > sem := Semaphore new. > gotSem := sem waitMaxTime: 45. > > This methods returns true if a could enter the critical section. But if I'm blocked, I am only willing to wait for 45 seconds. If I cannot enter the critical section in this time, the method returns false and i can react on this timeout. > > Has anybody seen such a behaviour in VisualWorks? > > Greetings > > Klasu Muelheims > > > Collogia AG > Ubierring 11 > > 50678 Köln > Germany > +49 221 336080 > http://www.collogia.de > > > Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt. > > > Diese Nachricht ist vertraulich. Wenn Sie nicht der beabsichtigte Empfänger sind, informieren Sie bitte den Absender. Das unbefugte Kopieren oder Weiterleiten ist nicht gestattet. Wegen der Manipulierbarkeit von E-Mails übernehmen wir keine Haftung für den Inhalt. |
Free forum by Nabble | Edit this page |