[squeak-dev] Transcript error when forceUpdate: false (?)

Levente Uzonyi leves at caesar.elte.hu
Wed Jan 27 22:05:07 UTC 2021

Hi Marcel,

On Tue, 26 Jan 2021, Marcel Taeumel wrote:

> Hi Jaromir,
> please take a look at Collections-mt.923 (inbox). Maybe those changes would satisfy all your current needs in this regard. :-)
> @all: Would Transcript now be thread-safe? Did I miss something?

Not at all. The problem is not #endEntry but all the other 
methods writing to the stream e.g.: #nextPutAll:.
The real solution is to replace the stream-like API with one that provides 
an easy way to write messages in a thread-safe way. E.g.:

Transcript showStream: [ :stream |
 	stream nextPutAll: 'Hello'; space; nextPutAll: ' World!'; cr ]

Which guarantees that 'Hello World!' appears on the Transcript without 
being mixed with other messages.


Transcript show: 'Hello {1}!{2}' format: { 'World'. String cr }.

The implementations could be e.g.:

showStream: aBlock

 	| string |
 	string := String streamContents: aBlock.
 	self safelyNextPutAll: string

show: aString format: arguments

 	| string |
 	string := aString format: arguments.
 	self safelyNextPutAll: string

The last challenge is to implement #safelyNextPutAll: which involves 
making Transcript not be a TranscriptStream.
Transcript should encapsulate the stream and use a Mutex (not a global one 
because its pointless) to provide thread-safety while writing the 
characters on it or reading its contents. E.g.:

safelyNextPutAll: aString

 	mutex critical: [
 		stream nextPutAll: aString ]

For backwards compatibility, the stream-API methods must be provided for a 
while but those methods should be thread-safe on their own. E.g.:

nextPutAll: aString

 	self safelyNextPutAll: aString

nextPut: aCharacter

 	self safelyNextPutAll: aCharacter asString


> Best,
> Marcel
>       Am 25.01.2021 21:38:36 schrieb jaromir <m at jaromir.net>:
>       Well, I tried deferring the whole Transcript endEntry machinery to the UI
>       doOneCycle (bypassing the changed: #appendEntryLater mechanism) for
>       #forceUpdate = false only ... and it seems to avoid the problem!
>       TranscriptStream >> endEntry
>       deferredEntry ifNil: [ false ]. "this is a new instance variable"
>       self semaphore critical:[
>       self class forceUpdate
>       ifTrue: [self changed: #appendEntry; reset]
>       ifFalse: [deferredEntry := true].
>       TranscriptStream >> flushDeferredEntry
>       "This is run every UI cycle in doOneCycleNowFor:"
>       deferredEntry ifTrue: [
>       self class forceUpdate: true.
>       self endEntry.
>       deferredEntry := false.
>       self class forceUpdate: false.
>       ]
>       doOneCycleNowFor: aWorld
>       "... the whole body remains unchanged except:"
>       capturingGesture ifFalse:
>       [aWorld runStepMethods.
>       Transcript flushDeferredEntry. "this is printing for #forceUpdate =
>       false"
>       self displayWorldSafely: aWorld].
>       For #forceUpdate = true the endEntry mechanism remains unchanged and failing
>       as before...
>       --
>       Sent from: http://forum.world.st/Squeak-Dev-f45488.html

More information about the Squeak-dev mailing list