dale could you publish your code and open a BT entry so that a person with a better understanding of the implications than me can comment on it? On Aug 7, 2009, at 11:28 PM, Dale Henrichs wrote:
Stef,
I'm not sure that concurrent use of the ThreadSafe Transcript is any more or less dangerous from the foreground process than from background process.
I've experimented with a mod to ThreadSafeTranscript>>endEntry that allows for both foreground and background updating of the transcript. The following expression:
| tt | tt := (Smalltalk at: #Transcript). "Background updates" [1 to: 20 do: [:i | tt nextPutAll: '[', i printString, ']'; nextPutAll: '*'; flush . Processor yield ]. tt flush ] fork. "Background updates" [100 to: 120 do: [:i | tt nextPutAll: '{', i printString, '}'; nextPutAll: '-'; flush. Processor yield ]. tt flush ] fork. "Foreground updates" 200 to: 220 do: [:i | tt show: '---', i printString, '---'. Processor yield ]
produces this output in the transcript:
---200---[1]{100}*---201----[2]---202---*{101}----203--- [3]*{102}---204----[4]*---205---{103}-[5]---206---*{104}----207--- [6]*{105}---208----[7]*---209---{106}-[8]---210---*{107}----211--- [9]*{108}---212----[10]*---213---{109}-[11]---214---*{110}----215--- [12]*{111}---216----[13]*---217---{112}-[14]---218---*{113}----219--- [15]*{114}---220----[16]*{115}-[17]*{116}-[18]*{117}-[19]*{118}- [20]*{119}-{120}-
I protected the #changed: message and the #displayWorldSafely with the access semaphore so at a minimum concurrent transcript accesses shouldn't be a problem. With this mod,the transcript updates when called from a lone foreground process, too.
If you want, I can can submit a bug along with the proposed fix...Alternatively, I think I've probably got enough info to fix my problem in isolation.
Hmmm, perhaps WorldState needs a mutex to make #displayWorldSafely truly safe?
Dale
----- "Stéphane Ducasse" <stephane.ducasse@inria.fr> wrote:
| I m not really satisfied of what I did but I think that this is | important to have a thread safe transcript. | Now I have the impression that the Morphic concurrency model could | really be rethought. | I'm not good enough with process and the rest but I got so burnt by | it | (I had to cancel work made by nathanael for the botsinc environment | | to have animation in BotsInc | because they worked on PC but blocked the UI on mac). | | On Aug 7, 2009, at 9:06 PM, Dale Henrichs wrote: | | > Igor, | > | > I appreciate what you are saying and in the fullness of time, we may | | > be able to do more things with background processes. | > | > However, we _are_ running a development environment for GemStone | > that should appear to the user to be no different than the Pharo | > development environment ... i.e., when you evaluate the following | > expression in Pharo or The GemTools client: | > | > 10 timesRepeat: [ (Delay forSeconds: 1) wait ] | > | > you would expect the UI process to be blocked for the duration of | > execution. This is why I _block_ the UI process during execution. | > | > If you have a long running process running in the foreground | > (whether or not it is running on GemStone) you expect to be able to | | > interrupt the process and bring up a debugger on the interrupted | > process. In order to do that with the GemTools client, we have to | > use a non-blocking C call, so that the GemTools client can recognize | | > the interrupt and take appropriate action. This is why we are using | | > a non-blocking call. | > | > With that said, something subtle _has_ changed in the way that the | | > Pharo UI processes updates windows ... In earlier versions of Pharo, | | > the Transcript window (whether or not it was thread-safe) updated | > without any special effort on my part, with the 1.0 beta, the | > transcript window is not updating. I've tried both thread safe and | | > non-thread safe Transcripts and it doesn't appear to matter. | > | > While poking around, I have discovered that the transcript is not | > updated until the process finishes in Pharo either. So the following | | > expression "misbehaves" whether executed in GemStone or Pharo: | > | > 10 timesRepeat: [ | > (Delay forSeconds: 1) wait. | > Transcript cr; show: 'hi' ] | > | > I guess I _expect_ the display to be updated whether or not I am | > running a process in the foreground. | > | > If I insert a 'World displayWorldSafely' into the loop then the | > transcript is updated 'correctly': | > | > 10 timesRepeat: [ | > (Delay forSeconds: 1) wait. | > Transcript cr; show: 'hi'. | > World displayWorldSafely ] | > | > Is this expected behavior and the correct solution to my problem? | > | > Dale | > ----- "Igor Stasenko" <siguctua@gmail.com> wrote: | > | > | 2009/8/7 Dale Henrichs <dale.henrichs@gemstone.com>: | > | > I'm trying to characterize some differences in behavior for | > GemTools | > | between Squeak and the 1.0beta for Pharo. I'm not reporting a bug | as | > | much as trying to understand what I need to do differently in | Pharo. | > | > | > | > In GemTools, I have a special workspace (GemTools Launcher), | that | > | causes doits to be evaluated in a GemStone server. This is done | by | > | using FFI to make calls to the GemStone GCI library. | > | > | > | > The string is passed to GemStone via a nonblocking C call. On | the | > | Pharo (client) side, we poll for a result. While an expression is | > | evaluating, exceptions may be raised on the server-side and on | the | > | client, we convert the gemstone exception into a Pharo exception | and | > | signal it, if/when the exception is resumed, we pass a result back | | > to | > | the server and continue waiting for the result of the original | > | expression. | > | > | > | > There are two thing that might happen when a exception is raised | | > in | > | this manner. If the exception is an error, we bring up a debugger | > | window on the client and arrange to debug the process on the | server | > | (again using the GCI). If the exception is what we call a Client | > | Forwarder exception, then we arrange to send a message to the | client | > | object and pass the result back to the server side. Using a | client | > | forwarder, the server can send messages to the client Transcript | | > with | > | logging/progress messages. | > | > | > | > In earlier versions of Pharo and in the current version of | Squeak, | > | when we sent messages to the Transcript, the messages would show | up | > | immediately ... making it easy to watch progress of long running | > | operations. | > | > | > | > In the 1.0 beta Pharo, this behavior has changed. It appears | that | > | the Transcript window is not updated until the polling process | > | finishes, which makes the progress messages a little bit less | than | > | useful. | > | > | > | > I assume that I need to add a message to my polling loop to | allow | > | for display updates...I'm doing a Delay wait in the loop so the | > | process is not in a tight loop. | > | > | > | > I am not running the poll in the background, because I want the | UI | > | process to be blocked ... this same mechanism is used for menu | > items, | > | etc. so blocking is important. | > | > | > | > Thanks for the help, | > | | > | Dale, the key problem of this is that 'wait loop' blocks the UI | > | process. I know, it is simplest way to prevent user from doing | > | anything while system is busy but its not very friendly, | especially | > | when you need to perform a remote processing which requires a | > | substantional amount of time to complete. | > | But, i wonder, what is the point in using a non-blocking calls to | > | communicate with GemStone, when in the end its still blocks | > | everything | > | (from user's point of view) ? :) | > | | > | Stef did a good job making a Transcript thread-safe in Pharo, so | it | > | can be used by any process (not only UI one) safely. | > | But this implies that you should not block the UI thread to give | | > it a | > | chance to update the screen. In case if nothing blocks the | process, | > | the transcript window will be updated each 20ms or so (World | update | > | cycle), and such delay, i think will be hardly noticeable by | users. | > | Transcript is a stream , which updated immediately once you | putting | > | something to it, but there are no guarantees that any other | objects | > | (like window , which is displaying its contents) should be | updated | > | immediately as well. | > | | > | I am encouraging you to create a background process , which talks | > | with | > | GemStone, and then UI process just schedule user actions to it. | This | > | will make UI process non-blocking, but of course, requires | > additional | > | efforts, like disabling the user from doing anything while | waiting | > | response from G/S. But this could be done nicely, and user could | go | > | to | > | any other window/menu etc, and do things there while G/S | processing | > | the actions. Which i think makes UI much more friendly. | > | | > | | > | > | > | > Dale | > | > | > | > _______________________________________________ | > | > Pharo-project mailing list | > | > Pharo-project@lists.gforge.inria.fr | > | > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo- | > project | > | > | > | | > | | > | | > | -- | > | Best regards, | > | Igor Stasenko AKA sig. | > | > _______________________________________________ | > Pharo-project mailing list | > Pharo-project@lists.gforge.inria.fr | > http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo- project