Hi Ben,

> On 11 Jan 2020, at 10:50, Ben Coman <b...@openinworld.com> wrote:
> 
> 
> 
> On Sat, 11 Jan 2020 at 06:31, Sven Van Caekenberghe <s...@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. 

OK, I can understand that, the question remains what happens when the processes 
have equal priorities.

> 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.

These are clear statements.

> 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'

OK, good example: I think/hope I understand.

Now, these further examples only strengthen my believe that it is simply 
impossible to talk about semaphores without talking about (the complexities) of 
process scheduling.

Semaphores exist as a means to coordinate processes, hence when using them you 
have to understand what (will) happen, and apparently that is quite complex.

In any case, thanks again for the explanations,

Sven

> 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.
> Not needing to trace "Original process" in the first example gives less for 
> the reader to digest  
> 
> So your first example might 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: 20.
> p2 := [
>    trace value: 'Process 2a signals semaphore'. 
>    semaphore signal.
>    trace value: 'Process 2b continues' ] forkAt: 30.
> 
> ==>
> '@30 Process 1a waits for signal on semaphore'
> '@20 Process 2a signals semaphore'
> '@30 Process 1b received signal'
> '@20 Process 2b continues'
> 
> 
> with the priority order swapped...
> | 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.
> 
> ==>
> '@30 Process 2a signals semaphore'
> '@30 Process 2b continues'
> '@20 Process 1a waits for signal on semaphore'
> '@20 Process 1b received signal'
> 
> 
> cheers -ben


Reply via email to