[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.
or
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
Levente
>
> 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
|