-
-
Notifications
You must be signed in to change notification settings - Fork 361
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add an "exit condition" to the UI loop to allow a former UI process t… #11455
base: Pharo13
Are you sure you want to change the base?
Add an "exit condition" to the UI loop to allow a former UI process t… #11455
Conversation
failing test not related:
|
Hi Denis,
[1/0] forkAt: Processor activePriority + 1. Perfect example :) I understand now that when the [1/0] process requests a new debugger the UI is waiting on a ProcessList, i.e. not on a Semaphore, and yet we'd like the UI to open a new debugger. It's clear then, as you suggested, that distinguishing where exactly the UI is waiting is not helpful. I'd like to suggest the simplest possible solution here: Always create a new UI process for a new debug request. This way you'll make sure the current UI will be able to finish whatever it is doing (a Playground example or any deferred action) and automatically terminate when it reaches the end of its current cycle. And at the same time the new UI will be able to open the requested debugger immediately and start acting as a proper new UI. An alternative could be trying to distinguish when the UI is idly waiting (on a ProcessList between cycles or an intercycle delay semaphore) or busy running it's intracycle errands (e.g. by placing a boolean flag inside the cycle's code) but I can't see any added value here. So unless I missed some fatal downside I prefer the former, simple solution.
Can't agree more :) It seems to me though "any" code fragment should now produce identical outcome regardless whether it's run in the UI (Playground) or otherwise (forked) ("any" code meaning, of course, except e.g. a code referring to the UI process itself :) etc. ). Or at least we're getting closer to the "ideal". Surprisingly, even the following example works, i.e. opens a debugger instead of getting stuck, but in this case it is also thanks to some unrelated system interrupts at play preempting the old UI and allowing the new UI run.. [1/0] fork. Please check the latest commit. I'd very much appreciate your view. |
failing test in CI: CoNarrowHistoryFetcherTest>>testNarrowingReturnsSameElementsThatCallingDirectly |
@isCzech I like how simple it is now. Thanks for this work. CoNarrowHistoryFetcherTest is not related. I have another PR with same errors. |
Hi, I was checking this, long discussion. |
Hi @guillep . s := Semaphore new.
[1/0. s signal] fork.
s wait Execute this code from the playground and the image will be locked. The debugger from the background process will not be shown. Another example without semaphore: s := Semaphore new.
[1/0. s signal] fork.
[] repeat. The explanation is quite simple: to open the debugger the UI process should be "free" to process the "debugger request". If the UI process is busy on something then any new UI action (like a debugger request) will wait until the UI process will be free. The proposed solution is quite elegant:
Does it make sense? |
@isCzech could you resolve conflicts? |
Hi @dionisiydk I wonder why has the conflict popped up but I have no experience in this regard. IMO nothing changed in the original Pharo code and the suggestion in this PR is still valid. May I ask you to doublecheck? I trust you have lot of experience :) |
It seems you did everything. |
I restarted the build on CI and there are failing tests. |
I updated the base to be Pharo 12 |
@@ -648,11 +648,11 @@ MorphicUIManager >> showWaitCursorWhile: aBlock [ | |||
{ #category : #'ui process' } | |||
MorphicUIManager >> spawnNewProcess [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Pharo12 method neeeds to be copied to MorphicCoreUIManager (where it is duplicated)
I am pretty familiar with Dolphin Smalltalk's UI code, and it indeed uses a very similar core approach of exiting the message loop when that particular process is no longer the One True UI Process, allowing the new one to take over smoothly. A neat bit of convergent evolution! However I have one concern: Message processing in Dolphin is much more fine-grained, as it can rely on Windows to do most of the heavy lifting WRT determining need-to-paint—so there's no internal concept of a render cycle, it just processes This actually would already cause problems with the existing case where a new UI process is spawned, that of debugging the UI process, except that there is an awful hack of a workaround already in place. In
It looks like I'm not sure how to address this cleanly without a need for massive refactoring, or indeed at all—I know too little about how Pharo interacts with the host OS to be confident. I have some vague ideas about how to tease things out if anyone is interested, but it'd be easiest to chat about it on Discord or something rather than try to write it up all at once here. (Another difference that's worth noting and may be relevant—in Dolphin the UI process blocks entirely waiting for new events from the OS, relying on the idle process to take over and quiesce the VM. Pharo seems instead to explicitly poll for events every ~16ms and execute a (potential) render cycle each time. Clearly there is dirty-checking as idle CPU usage is minimal, but the image still wakes and executes at least some code each cycle.) |
cb5c17c
to
8b7f43f
Compare
…o finish its last cycle and terminate automatically when replaced by a new UI. This change could allow UI processes blocked on custom semaphores to continue waiting for a signal and finish their previous job before terminating automatically. Useful for keeping the UI responsive during evaluation of examples like this: s := Semaphore new. [1/0. s signal] fork. s wait This is a first approxiamation of the solution and may require some polishing :)
… variable (e.g. Semaphore or other locking mechanisms).
…finish its tasks in its current cycle and terminate automatically. This commit extends creating a new UI for all debug requests rather than only those occuring when the current UI is blocked on a semaphore. This approach aims at improving UI responsivness and unifying behavior for code fragments regardless whether they are started from the UI (Playground) or in a separate process (forked). For examples see previous discussion.
dea7711
to
4af467e
Compare
4af467e
to
46cb4cd
Compare
…o finish its last cycle and terminate automatically when replaced by a new UI. This change could allow UI processes blocked on custom semaphores to continue waiting for a signal and finish their previous job before terminating automatically. Useful for keeping the UI responsive during evaluation of examples like this:
s := Semaphore new.
[1/0. s signal] fork.
s wait
This is a first approxiamation of the solution and may require some polishing :)