Transcript error when forceUpdate: false (?)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
27 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

Christoph Thiede

I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?


Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 11:13:55
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Christoph.

 What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)

It's only part of the problem. There could be a disconnect between the former "Project current uiProcess" comparison and how "addDeferredUIMessage" is processed later in the code. It would be better to no preempt this call as a whole.

Best,
Marcel

Am 28.01.2021 10:59:50 schrieb Thiede, Christoph <[hidden email]>:

Hi all,


this is an interesting discussion, two thoughts from my side:


1. What is the problem with "Processor activeProcess == Project current uiProcess" not being a thread-safe expression? I see that it could be possible at many points that the VM interrupts the current process and resumes another one first; but still, activeProcess will always hold the same Process instance when the same process is active, independently of any interruptions, won't it? What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)


2. To Levente's proposal of making Transcript calls thread-safe:


safelyNextPutAll: aString

>          mutex critical: [
>                  stream nextPutAll: aString ]

So this would delay the execution of any process that uses the Transcript, wouldn't it? Hm ... I would rather have expected the Transcript calls to be deferred when the Transcript is locked ATM - *unless* #forceUpdate is enabled, maybe. Let's keep everyday Transcript clients blocking-free whenever possible. Or imagine several processes writing to the Transcript, but the transcript not being opened at this time. There should no need to block any of the calling processes?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 10:41:03
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Tobias

A separate kind of log (that optionally could output to the transcript)

Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)

Best,
Marcel

Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:

Hi

apart from the debuggers, why bother making Transcript thread-safe in the first place?

The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.

A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
Thread safety could be addressed there without complicating Transcript more…

my 2ct
-tobias


> On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>
> Hi Levente.
>
> Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>
> (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>
> Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>
> Best,
> Marcel
>> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>
>> 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 :
>> >
>> > 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
>> >
>> >
>> >
>>
>





Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

marcel.taeumel
I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?

If that code runs at 39 and the user switches projects at 40, yes, this can happen.

Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)

Even the implementation of #evaluateUIMessage: would need something like <noContextSwitch> :-) So, one could directly add this pragma to, for example, #endEntry, without adding such a new indirection. And at lower levels or more concise scopes, access should be controlled with a mutex.

I suppose that the "trick" with <noContextSwitch> only works in a green-threading model where exactly 1 thread (or Squeak process) is actually running at a time.

Best,
Marcel

P.S.: Is every fallback code for failing primitives evaluated without preemption? 

Am 28.01.2021 11:28:24 schrieb Thiede, Christoph <[hidden email]>:

I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?


Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 11:13:55
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Christoph.

 What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)

It's only part of the problem. There could be a disconnect between the former "Project current uiProcess" comparison and how "addDeferredUIMessage" is processed later in the code. It would be better to no preempt this call as a whole.

Best,
Marcel

Am 28.01.2021 10:59:50 schrieb Thiede, Christoph <[hidden email]>:

Hi all,


this is an interesting discussion, two thoughts from my side:


1. What is the problem with "Processor activeProcess == Project current uiProcess" not being a thread-safe expression? I see that it could be possible at many points that the VM interrupts the current process and resumes another one first; but still, activeProcess will always hold the same Process instance when the same process is active, independently of any interruptions, won't it? What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)


2. To Levente's proposal of making Transcript calls thread-safe:


safelyNextPutAll: aString

>          mutex critical: [
>                  stream nextPutAll: aString ]

So this would delay the execution of any process that uses the Transcript, wouldn't it? Hm ... I would rather have expected the Transcript calls to be deferred when the Transcript is locked ATM - *unless* #forceUpdate is enabled, maybe. Let's keep everyday Transcript clients blocking-free whenever possible. Or imagine several processes writing to the Transcript, but the transcript not being opened at this time. There should no need to block any of the calling processes?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 10:41:03
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Tobias

A separate kind of log (that optionally could output to the transcript)

Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)

Best,
Marcel

Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:

Hi

apart from the debuggers, why bother making Transcript thread-safe in the first place?

The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.

A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
Thread safety could be addressed there without complicating Transcript more…

my 2ct
-tobias


> On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>
> Hi Levente.
>
> Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>
> (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>
> Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>
> Best,
> Marcel
>> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>
>> 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 :
>> >
>> > 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
>> >
>> >
>> >
>>
>





Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

Levente Uzonyi
In reply to this post by marcel.taeumel
Hi Christoph,

On Thu, 28 Jan 2021, Marcel Taeumel wrote:

> Hi Christoph.
> >  What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)
>
> It's only part of the problem. There could be a disconnect between the former "Project current uiProcess" comparison and how "addDeferredUIMessage" is processed later in the code. It would be better to no preempt this call as
> a whole.
>
> Best,
> Marcel
>
>       Am 28.01.2021 10:59:50 schrieb Thiede, Christoph <[hidden email]>:
>
>       Hi all,
>
>
>       this is an interesting discussion, two thoughts from my side:
>
>
>       1. What is the problem with "Processor activeProcess == Project current uiProcess" not being a thread-safe expression? I see that it could be possible at many points that the VM interrupts the current process and
>       resumes another one first; but still, activeProcess will always hold the same Process instance when the same process is active, independently of any interruptions, won't it? What is that dangerous thing that could
>       happen during a suspension point in the VM? What am I missing here? :-)
>
>
>       2. To Levente's proposal of making Transcript calls thread-safe:
>
>
>       > safelyNextPutAll: aString
>
>       > 
> >          mutex critical: [
> >                  stream nextPutAll: aString ]
>
> So this would delay the execution of any process that uses the Transcript, wouldn't it? Hm ... I would rather have expected the Transcript calls to be deferred when the Transcript is locked ATM - *unless* #forceUpdate
If you mean that the calling process has to wait until the mutex is
available and then until the string is written to the stream, then yes,
it is delayed. But that's no different from current behavior other than
having to synchronize with the other processes writing to/reading from the
stream which does not happen now and results in race conditions.

What do you mean by "Transcript calls to be deferred"? If you think that
holding the mutex would make the characters appear on the Transcript's
target, then no, they would just get written to the internal buffer.
When the message would be displayed is up to the UI.

> is enabled, maybe. Let's keep everyday Transcript clients blocking-free whenever possible. Or imagine several processes writing to the Transcript, but the transcript not being opened at this time. There should no need
> to block any of the calling processes?

What would be the reason to push the burden of Transcript synchronization
(which is actually impossible) onto the users?


Levente

>
> Best,
> Christoph
>
> _________________________________________________________________________________________________________________________________________________________________________________________________________________________________
> Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
> Gesendet: Donnerstag, 28. Januar 2021 10:41:03
> An: squeak-dev
> Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)  
> Hi Tobias
> > A separate kind of log (that optionally could output to the transcript)
>
> Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)
>
> Best,
> Marcel
>
>       Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:
>
>       Hi
>
>       apart from the debuggers, why bother making Transcript thread-safe in the first place?
>
>       The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.
>
>       A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
>       Thread safety could be addressed there without complicating Transcript more…
>
>       my 2ct
>       -tobias
>
>
>       > On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>       >
>       > Hi Levente.
>       >
>       > Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the
>       order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>       >
>       > (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a
>       Transcript window is open.)
>       >
>       > Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>       >
>       > Best,
>       > Marcel
>       >> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>       >>
>       >> 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 :
>       >> >
>       >> > 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
>       >> >
>       >> >
>       >> >
>       >>
>       >
>
>
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

Levente Uzonyi
In reply to this post by Tobias Pape
Hi Tobias,

On Thu, 28 Jan 2021, Tobias Pape wrote:

>
>
>> On 28. Jan 2021, at 10:41, Marcel Taeumel <[hidden email]> wrote:
>>
>> Hi Tobias
>>
>> > A separate kind of log (that optionally could output to the transcript)
>>
>> Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)
>>
>
> That's not what I meant.
>
> Transcript is Smalltalk for stdout, I would say.
> Complicating it to act like a proper logger is IMHO ill-directed.
>
> Neither C printf nor Java System.out.println[1] nor (i think) Racket display are thread safe.
Great examples. Let's not do what they do. We can easily provide a
thread-safe Transcript, so why not do so?

>
> And I think this is ok.
>
> Transcript shouldn't break when used concurrently, but I don't think it should do something sophisticated…

It does break now.

>
> Transcript is not a good logger. We shouldn't pretend it is.
>
> Maybe GemStone's object log is a neat abstraction. Thread-safe, object based, with time stamps.

Perhaps because Transcript is not a logger. It's just a place you can
write things to which will appear somewhere the user can see it.
It can do that trhing right or wrong. I think we all agree it does not do
it right now.


Levente

>
>
>
> Best regards
> -Tobias
>
> [1]: https://stackoverflow.com/questions/32880557/is-system-out-println-thread-safe-by-default
>> Best,
>> Marcel
>>> Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:
>>>
>>> Hi
>>>
>>> apart from the debuggers, why bother making Transcript thread-safe in the first place?
>>>
>>> The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.
>>>
>>> A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
>>> Thread safety could be addressed there without complicating Transcript more…
>>>
>>> my 2ct
>>> -tobias
>>>
>>>
>>> > On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>>> >
>>> > Hi Levente.
>>> >
>>> > Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>>> >
>>> > (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>>> >
>>> > Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>>> >
>>> > Best,
>>> > Marcel
>>> >> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>> >>
>>> >> 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 :
>>> >> >
>>> >> > 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
>>> >> >
>>> >> >
>>> >> >
>>> >>
>>> >
>>>
>>>
>>>
>>

Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

Tobias Pape
Hi


> On 28. Jan 2021, at 13:31, Levente Uzonyi <[hidden email]> wrote:
>
> Hi Tobias,
>
> On Thu, 28 Jan 2021, Tobias Pape wrote:
>
>>
>>
>>> On 28. Jan 2021, at 10:41, Marcel Taeumel <[hidden email]> wrote:
>>> Hi Tobias
>>> > A separate kind of log (that optionally could output to the transcript)
>>> Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)
>>
>> That's not what I meant.
>>
>> Transcript is Smalltalk for stdout, I would say.
>> Complicating it to act like a proper logger is IMHO ill-directed.
>>
>> Neither C printf nor Java System.out.println[1] nor (i think) Racket display are thread safe.
>
> Great examples. Let's not do what they do. We can easily provide a thread-safe Transcript, so why not do so?
>
>>
>> And I think this is ok.
>>
>> Transcript shouldn't break when used concurrently, but I don't think it should do something sophisticated…
>
> It does break now.

Yeah i see.

>
>>
>> Transcript is not a good logger. We shouldn't pretend it is.
>>
>> Maybe GemStone's object log is a neat abstraction. Thread-safe, object based, with time stamps.
>
> Perhaps because Transcript is not a logger. It's just a place you can write things to which will appear somewhere the user can see it.
> It can do that trhing right or wrong. I think we all agree it does not do it right now.

agreed.

But I'd rather see Transcript dumbed down, not clevered up.
-t


>
>
> Levente
>
>>
>>
>>
>> Best regards
>> -Tobias
>>
>> [1]: https://stackoverflow.com/questions/32880557/is-system-out-println-thread-safe-by-default
>>> Best,
>>> Marcel
>>>> Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:
>>>> Hi
>>>> apart from the debuggers, why bother making Transcript thread-safe in the first place?
>>>> The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.
>>>> A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
>>>> Thread safety could be addressed there without complicating Transcript more…
>>>> my 2ct
>>>> -tobias
>>>> > On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>>>> > > Hi Levente.
>>>> > > Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>>>> > > (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>>>> > > Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>>>> > > Best,
>>>> > Marcel
>>>> >> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>>> >> >> 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 :
>>>> >> >
>>>> >> > 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
>>>> >> > >> > >> >
>>>> >> >
>



Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

Christoph Thiede
In reply to this post by marcel.taeumel

Hi Marcel,


thanks for the explanation. Just to make sure I understand correctly: We are talking about maybe changing the transcript interface and/or even introducing a new pragma selector solely for the purpose of smoothly handling this super-edge case of the active project being switched just while an always-running background thread is logging something to the Transcript? This sounds a very bit speculative to me ... Is it really worth the raised complexity? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 12:14:11
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?

If that code runs at 39 and the user switches projects at 40, yes, this can happen.

Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)

Even the implementation of #evaluateUIMessage: would need something like <noContextSwitch> :-) So, one could directly add this pragma to, for example, #endEntry, without adding such a new indirection. And at lower levels or more concise scopes, access should be controlled with a mutex.

I suppose that the "trick" with <noContextSwitch> only works in a green-threading model where exactly 1 thread (or Squeak process) is actually running at a time.

Best,
Marcel

P.S.: Is every fallback code for failing primitives evaluated without preemption? 

Am 28.01.2021 11:28:24 schrieb Thiede, Christoph <[hidden email]>:

I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?


Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 11:13:55
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Christoph.

 What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)

It's only part of the problem. There could be a disconnect between the former "Project current uiProcess" comparison and how "addDeferredUIMessage" is processed later in the code. It would be better to no preempt this call as a whole.

Best,
Marcel

Am 28.01.2021 10:59:50 schrieb Thiede, Christoph <[hidden email]>:

Hi all,


this is an interesting discussion, two thoughts from my side:


1. What is the problem with "Processor activeProcess == Project current uiProcess" not being a thread-safe expression? I see that it could be possible at many points that the VM interrupts the current process and resumes another one first; but still, activeProcess will always hold the same Process instance when the same process is active, independently of any interruptions, won't it? What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)


2. To Levente's proposal of making Transcript calls thread-safe:


safelyNextPutAll: aString

>          mutex critical: [
>                  stream nextPutAll: aString ]

So this would delay the execution of any process that uses the Transcript, wouldn't it? Hm ... I would rather have expected the Transcript calls to be deferred when the Transcript is locked ATM - *unless* #forceUpdate is enabled, maybe. Let's keep everyday Transcript clients blocking-free whenever possible. Or imagine several processes writing to the Transcript, but the transcript not being opened at this time. There should no need to block any of the calling processes?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 10:41:03
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Tobias

A separate kind of log (that optionally could output to the transcript)

Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)

Best,
Marcel

Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:

Hi

apart from the debuggers, why bother making Transcript thread-safe in the first place?

The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.

A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
Thread safety could be addressed there without complicating Transcript more…

my 2ct
-tobias


> On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>
> Hi Levente.
>
> Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>
> (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>
> Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>
> Best,
> Marcel
>> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>
>> 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 :
>> >
>> > 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
>> >
>> >
>> >
>>
>





Carpe Squeak!
Reply | Threaded
Open this post in threaded view
|

Re: Transcript error when forceUpdate: false (?)

marcel.taeumel
Hi Christoph,

This sounds a very bit speculative to me ... Is it really worth the raised complexity? :-)

We are talking about whether <noContextSwitch> could help to make code thread-safe where a mutex might be not sufficient or possible.

Whether or not this is useful to the average Smalltalk programmer using Transcript is pure speculation. The underlying issue is, however, real. :-) Now, it depends, how critical the systems are that you are developing. So, for people that want to process critical data, Transcript must work ... or an alternative logging mechanism has to be created for that purpose. This leads to the discussion about the features the underlying framework/library should provide ... ;-)

Best,
Marcel

Am 01.02.2021 15:29:14 schrieb Thiede, Christoph <[hidden email]>:

Hi Marcel,


thanks for the explanation. Just to make sure I understand correctly: We are talking about maybe changing the transcript interface and/or even introducing a new pragma selector solely for the purpose of smoothly handling this super-edge case of the active project being switched just while an always-running background thread is logging something to the Transcript? This sounds a very bit speculative to me ... Is it really worth the raised complexity? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 12:14:11
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?

If that code runs at 39 and the user switches projects at 40, yes, this can happen.

Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)

Even the implementation of #evaluateUIMessage: would need something like <noContextSwitch> :-) So, one could directly add this pragma to, for example, #endEntry, without adding such a new indirection. And at lower levels or more concise scopes, access should be controlled with a mutex.

I suppose that the "trick" with <noContextSwitch> only works in a green-threading model where exactly 1 thread (or Squeak process) is actually running at a time.

Best,
Marcel

P.S.: Is every fallback code for failing primitives evaluated without preemption? 

Am 28.01.2021 11:28:24 schrieb Thiede, Christoph <[hidden email]>:

I still don't see the point. Are you saying that the current project or it's UI process could change during a VM suspension point?


Then, what about something like "Project current evaluateUIMessage: [...]", which will unpreemptedly (using the new primitive solution) check the UI process and either evaluate the message directly or defer it? :-)


Best,

Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 11:13:55
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Christoph.

 What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)

It's only part of the problem. There could be a disconnect between the former "Project current uiProcess" comparison and how "addDeferredUIMessage" is processed later in the code. It would be better to no preempt this call as a whole.

Best,
Marcel

Am 28.01.2021 10:59:50 schrieb Thiede, Christoph <[hidden email]>:

Hi all,


this is an interesting discussion, two thoughts from my side:


1. What is the problem with "Processor activeProcess == Project current uiProcess" not being a thread-safe expression? I see that it could be possible at many points that the VM interrupts the current process and resumes another one first; but still, activeProcess will always hold the same Process instance when the same process is active, independently of any interruptions, won't it? What is that dangerous thing that could happen during a suspension point in the VM? What am I missing here? :-)


2. To Levente's proposal of making Transcript calls thread-safe:


safelyNextPutAll: aString

>          mutex critical: [
>                  stream nextPutAll: aString ]

So this would delay the execution of any process that uses the Transcript, wouldn't it? Hm ... I would rather have expected the Transcript calls to be deferred when the Transcript is locked ATM - *unless* #forceUpdate is enabled, maybe. Let's keep everyday Transcript clients blocking-free whenever possible. Or imagine several processes writing to the Transcript, but the transcript not being opened at this time. There should no need to block any of the calling processes?

Best,
Christoph


Von: Squeak-dev <[hidden email]> im Auftrag von Taeumel, Marcel
Gesendet: Donnerstag, 28. Januar 2021 10:41:03
An: squeak-dev
Betreff: Re: [squeak-dev] Transcript error when forceUpdate: false (?)
 
Hi Tobias

A separate kind of log (that optionally could output to the transcript)

Transcript can use stdout already. Not sure we want to shift the problem to the user again ... :-/ "Every time you provide an option, you expect users to make a decision." :-)

Best,
Marcel

Am 28.01.2021 10:32:27 schrieb Tobias Pape <[hidden email]>:

Hi

apart from the debuggers, why bother making Transcript thread-safe in the first place?

The Transcript is a mere output stream for debugging/logging etc., our stdout or stderr.

A separate kind of log (that optionally could output to the transcript) would be more apt IMHO.
Thread safety could be addressed there without complicating Transcript more…

my 2ct
-tobias


> On 28. Jan 2021, at 09:05, Marcel Taeumel wrote:
>
> Hi Levente.
>
> Thanks für clarification. We are talking about more than one problem here. :-) I did just address the issue with errors/debuggers happening due to UI process disruptions. You are also concerned about the order of contents in the Transcript's contents. Both are very important and required for claiming that it would be thread-safe.
>
> (Which reminds me that I find it very strange that the UI components (e.g. PluggableTextMorph) do also check the Transcript's internal characterLimit. I would expect an append-only behavior when a Transcript window is open.)
>
> Anyway, your proposal about a safelyNextPut(All): looks good. :-) +1
>
> Best,
> Marcel
>> Am 27.01.2021 23:05:21 schrieb Levente Uzonyi :
>>
>> 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 :
>> >
>> > 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
>> >
>> >
>> >
>>
>





12