On 11 Jan 2020, at 10:50, Ben Coman <btc@openinworld.com> wrote:On Sat, 11 Jan 2020 at 06:31, Sven Van Caekenberghe <sven@stfx.eu> wrote:Hi Ben,
Great approach, though I would make one change to make your example completely copy/paste runnable.
Stef's original example:
| trace semaphore p1 p2 |
semaphore := Semaphore new.
trace := [ :message |��
�� �� �� ����('[{1}] {2}' format: { Processor activeProcess priority. message }) crLog ].
p1 := [��
�� �� �� ����semaphore wait.
�� �� �� ����trace value: 'Process 1' ] fork.
p2 := [
�� �� �� ����semaphore signal.
�� �� �� ����trace value: 'Process 2' ] fork.����
trace value: 'Original process pre-yield'.
Processor yield.
trace value: 'Original process post-yield'.����
Gives:
'[40] Original process pre-yield'
'[40] Process 2'
'[40] Original process post-yield'
'[40] Process 1'
But not running the yield section gives:��
'[40] Process 2'
'[40] Process 1'which is an identical result if the 'Original process' traces are filtered out.��From this it would seem that the code in p2 continues after signal and only later does p1 get past its wait.Yes, a #signal does not transfer execution unless the waiting-process that received the signal is a higher priority.Within the same priority, it just makes waiting-process runnable, and the highest-priority-runnable-process is the one that is run.����Playing with the priorities we can change that order (apparently);
| trace semaphore p1 p2 |
semaphore := Semaphore new.
trace := [ :message |��
�� �� �� ����('[{1}] {2}' format: { Processor activeProcess priority. message }) crLog ].
p1 := [��
�� �� �� ����semaphore wait.
�� �� �� ����trace value: 'Process 1' ] forkAt: 30.
p2 := [
�� �� �� ����semaphore signal.
�� �� �� ����trace value: 'Process 2' ] forkAt: 20.����
Gives:
'[30] Process 1'
'[20] Process 2'
Again, the yield section makes no difference. So something else happened.The yield made no difference because it only facilitates other processes at-the-SAME-priority getting a chance to run.Yield doesn't put the current-process to sleep, it just moves the process to the back of its-priority-runQueue. It gets to run again before any lower priority process gets a chance to run.Yielding will never allow a lower-priority-process to run.����For a lower-priority process to run, the current-process needs to sleep rather than yield.Indeed. I will add this note to my chapter.��Compare...| trace semaphore p1 p2 |
semaphore := Semaphore new.
trace := [ :message | ('@{1} {2}' format: { Processor activePriority. message }) crLog ].
p1 := [
�� ��trace value: 'Process 1a waits for signal on semaphore'.��
�� ��semaphore wait.
�� ��trace value: 'Process 1b received signal' ] forkAt: 30.
p2 := [
�� ��trace value: 'Process 2a signals semaphore'.��
�� ��semaphore signal.
�� ��trace value: 'Process 2b continues' ] forkAt: 20.trace value: 'Original process pre-yield'.
Processor yield.
trace value: 'Original process post-yield'.��==>'@40 Original process pre-yield'
'@40 Original process post-yield'
'@30 Process 1a waits for signal on semaphore'
'@20 Process 2a signals semaphore'
'@30 Process 1b received signal'
'@20 Process 2b continues'with...| trace semaphore p1 p2 |
semaphore := Semaphore new.
trace := [ :message | ('@{1} {2}' format: { Processor activePriority. message }) crLog ].
p1 := [
�� ��trace value: 'Process 1a waits for signal on semaphore'.��
�� ��semaphore wait.
�� ��trace value: 'Process 1b received signal' ] forkAt: 30.
p2 := [
�� ��trace value: 'Process 2a signals semaphore'.��
�� ��semaphore signal.
�� ��trace value: 'Process 2b continues' ] forkAt: 20.trace value: 'Original process pre-delay'.
1 milliSecond wait.
trace value: 'Original process post-delay'.�� ��
==>'@40 Original process pre-delay'
'@30 Process 1a waits for signal on semaphore'
'@20 Process 2a signals semaphore'
'@30 Process 1b received signal'
'@20 Process 2b continues'
'@40 Original process post-delay'
Stef, on further consideration I think your first examples should not-have p1 and p2 the same priority.Scheduling of same-priority processes and how they interact with the UI thread is an extra level of complexity that may be better done shortly after.Yes I realize it.��Not needing to trace "Original process" in the first example gives less for the reader to digest����Yes I thought the same.��I thought that I could have the following strategy.��Give a first simple version, them revisiting it after.��