Semaphore wait and signal

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

Semaphore wait and signal

vinref
Hello

I am playing around with Semaphore, and wrote the following:

| coll count sem |
coll := Array withAll: (1 to: 100).
count := 0.
sem := Semaphore new.
coll do: [ :each |
    count := count + 1.
    (count >= 5)
        ifTrue: [    
            Transcript show: 'waiting...'; cr.
            sem wait ].
       
    [ [ 2 seconds asDelay wait.
         Transcript show: each printString, ' ', count printString; cr ] ensure: [ 
            count := count -1.
            sem signal ] ] fork ]

The output is:

waiting...
1  End of statement list encountered ->5
2 4
3 3
4 2
waiting...
waiting...
waiting...
waiting...
5 8
6 7
7 6
8 5
9 4
10 3
11 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
12 11
13 10
14 9
15 8
16 7
17 6
18 5
19 4
20 3
21 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
22 14
23 13
24 12
25 11
26 10
27 9
28 8
29 7
30 6
31 5
32 4
33 3
34 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
35 17
36 16
37 15
38 14
39 13
40 12
41 11
42 10
43 9
44 8
45 7
46 6
47 5
48 4
49 3
50 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
51 20
52 19
53 18
54 17
55 16
56 15
57 14
58 13
59 12
60 11
61 10
62 9
63 8
64 7
65 6
66 5
67 4
68 3
69 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
70 23
waiting...
71 23
72 22
73 21
74 20
75 19
76 18
77 17
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
78 23
79 22
80 21
81 20
82 19
83 18
84 17
85 16
86 15
87 14
88 13
89 12
90 11
91 10
92 9
93 8
94 7
95 6
96 5
97 4
98 3
99 2
100 1

I was expecting 'waiting...' to alternate with the 'each-count' lines. Also the entire statement paused for 2 seconds, spat out some lines, then waited a little longer, and then finished.

Can someone please explain this pattern?

Thanks, Vince
Reply | Threaded
Open this post in threaded view
|

Re: Semaphore wait and signal

jfabry
Hi Vince,

some of your problem may be in the Transcript buffering some of its output. It is best to add a ; flush to the end of all your printing, e.g. Transcript show: 'waiting...'; cr ; flush.

HTH

On May 10, 2016, at 07:31, Vince Refiti <[hidden email]> wrote:

Hello

I am playing around with Semaphore, and wrote the following:

| coll count sem |
coll := Array withAll: (1 to: 100).
count := 0.
sem := Semaphore new.
coll do: [ :each |
    count := count + 1.
    (count >= 5)
        ifTrue: [    
            Transcript show: 'waiting...'; cr.
            sem wait ].
       
    [ [ 2 seconds asDelay wait.
         Transcript show: each printString, ' ', count printString; cr ] ensure: [ 
            count := count -1.
            sem signal ] ] fork ]

The output is:

waiting...
1  End of statement list encountered ->5
2 4
3 3
4 2
waiting...
waiting...
waiting...
waiting...
5 8
6 7
7 6
8 5
9 4
10 3
11 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
12 11
13 10
14 9
15 8
16 7
17 6
18 5
19 4
20 3
21 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
22 14
23 13
24 12
25 11
26 10
27 9
28 8
29 7
30 6
31 5
32 4
33 3
34 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
35 17
36 16
37 15
38 14
39 13
40 12
41 11
42 10
43 9
44 8
45 7
46 6
47 5
48 4
49 3
50 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
51 20
52 19
53 18
54 17
55 16
56 15
57 14
58 13
59 12
60 11
61 10
62 9
63 8
64 7
65 6
66 5
67 4
68 3
69 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
70 23
waiting...
71 23
72 22
73 21
74 20
75 19
76 18
77 17
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
78 23
79 22
80 21
81 20
82 19
83 18
84 17
85 16
86 15
87 14
88 13
89 12
90 11
91 10
92 9
93 8
94 7
95 6
96 5
97 4
98 3
99 2
100 1

I was expecting 'waiting...' to alternate with the 'each-count' lines. Also the entire statement paused for 2 seconds, spat out some lines, then waited a little longer, and then finished.

Can someone please explain this pattern?

Thanks, Vince



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile

Reply | Threaded
Open this post in threaded view
|

Re: Semaphore wait and signal

philippeback
Transcript output logic is wicked, flush or not. Especially if you Halt now.

Check for stepGlobal senders and implmenters and see it in all its glory with flags and all.

You can then understand why things are weird.

Some World doOneCycle peppered around may confuse things a bit more.

Use a log file and tail -f it if you are on OSX or Linux.

It will at least be in the order you issue things.

Phil


On Tue, May 10, 2016 at 1:15 PM, Johan Fabry <[hidden email]> wrote:
Hi Vince,

some of your problem may be in the Transcript buffering some of its output. It is best to add a ; flush to the end of all your printing, e.g. Transcript show: 'waiting...'; cr ; flush.

HTH

On May 10, 2016, at 07:31, Vince Refiti <[hidden email]> wrote:

Hello

I am playing around with Semaphore, and wrote the following:

| coll count sem |
coll := Array withAll: (1 to: 100).
count := 0.
sem := Semaphore new.
coll do: [ :each |
    count := count + 1.
    (count >= 5)
        ifTrue: [    
            Transcript show: 'waiting...'; cr.
            sem wait ].
       
    [ [ 2 seconds asDelay wait.
         Transcript show: each printString, ' ', count printString; cr ] ensure: [ 
            count := count -1.
            sem signal ] ] fork ]

The output is:

waiting...
1  End of statement list encountered ->5
2 4
3 3
4 2
waiting...
waiting...
waiting...
waiting...
5 8
6 7
7 6
8 5
9 4
10 3
11 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
12 11
13 10
14 9
15 8
16 7
17 6
18 5
19 4
20 3
21 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
22 14
23 13
24 12
25 11
26 10
27 9
28 8
29 7
30 6
31 5
32 4
33 3
34 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
35 17
36 16
37 15
38 14
39 13
40 12
41 11
42 10
43 9
44 8
45 7
46 6
47 5
48 4
49 3
50 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
51 20
52 19
53 18
54 17
55 16
56 15
57 14
58 13
59 12
60 11
61 10
62 9
63 8
64 7
65 6
66 5
67 4
68 3
69 2
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
70 23
waiting...
71 23
72 22
73 21
74 20
75 19
76 18
77 17
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
waiting...
78 23
79 22
80 21
81 20
82 19
83 18
84 17
85 16
86 15
87 14
88 13
89 12
90 11
91 10
92 9
93 8
94 7
95 6
96 5
97 4
98 3
99 2
100 1

I was expecting 'waiting...' to alternate with the 'each-count' lines. Also the entire statement paused for 2 seconds, spat out some lines, then waited a little longer, and then finished.

Can someone please explain this pattern?

Thanks, Vince



---> Save our in-boxes! http://emailcharter.org <---

Johan Fabry   -   http://pleiad.cl/~jfabry
PLEIAD and RyCh labs  -  Computer Science Department (DCC)  -  University of Chile


Reply | Threaded
Open this post in threaded view
|

Re: Semaphore wait and signal

Ben Coman
In reply to this post by vinref
On Tue, May 10, 2016 at 6:31 PM, Vince Refiti <[hidden email]> wrote:

> Hello
>
> I am playing around with Semaphore, and wrote the following:
>
> | coll count sem |
> coll := Array withAll: (1 to: 100).
> count := 0.
> sem := Semaphore new.
> coll do: [ :each |
>     count := count + 1.
>     (count >= 5)
>         ifTrue: [
>             Transcript show: 'waiting...'; cr.
>             sem wait ].
>
>     [ [ 2 seconds asDelay wait.
>          Transcript show: each printString, ' ', count printString; cr ]
> ensure: [
>             count := count -1.
>             sem signal ] ] fork ]
>
> The output is:

[snipped]

> I was expecting 'waiting...' to alternate with the 'each-count' lines. Also
> the entire statement paused for 2 seconds, spat out some lines, then waited
> a little longer, and then finished.
>
> Can someone please explain this pattern?
>
> Thanks, Vince

Hi Vince,

General things to be aware of...
* Transcript is not perturbing your result.
* Playground code is executed in the context of the main UI-process. Thus...
  * An infinite loop will lock the UI.
  * A sem wait will lock the UI.
* Processes at the same priority are scheduled cooperatively.
* Processes at different priority are pre-emptively scheduled.

I refactored your example to better highlight program flow...

| coll count sem |
Transcript clear.
coll := Array withAll: (1 to: 99).
count := 0.
sem := Semaphore new.
coll do:
[   :each |
    count := count + 1.
   Transcript crShow: each printString; tab; tab; show: count printString, '+'.
   (count >= 5) ifTrue:
         [ sem isSignaled
             ifTrue: [   Transcript tab; show: ' nowait'.
                              sem wait ]
             ifFalse: [ Transcript tab; show: ' wait'.
                             sem wait.
                             Transcript crShow: each printString; tab;
tab; show: count printString; tab; show: ' postwait, excessSignals ' ,
sem excessSignals printString. ]
].

   [  Transcript crShow: ' ', each printString; tab; tab; show: count
printString; tab; show: ' delay'.
      2 seconds asDelay wait.
       count := count -1.
      Transcript crShow: ' ', each printString; tab ; tab; show: count
printString, '-'; tab; show: ' signal'.
      sem signal.
    ] fork.
]

You will need to add...
    Semaphore>>excessSignals
         ^excessSignals


For counts 1, 2, 3 & 4, forked processes -1 to -4 are queued to run,
but don't run until the UI-process suspended by the wait at each=5,
count=5, which is why the "waiting..." tag appears first.

When the UI-process waits, processes -1 to -4 run in turn and
immediately delay for two seconds. After this, they queued to run.
Process-1 signals the UI-process to be queued to run.  But processes
-2 to -4 run first, signalling sem an extra three times.

When the UI-process resumes, each=5, count=1 and sem has three
excessSignals.  Completing the do: adds process -5 to the run queue.
Then counts 2, 3, & 4 queues processes -6, -7 & -8 to run.  Counts 5,
6 & 7 consume the excessSignals without suspending, queing processes
-9, -10 & -11 to run.

At count=8, the UI-process suspends at the wait, and process -5 runs.
This signals the UI-process to be queued to run.  Processes -6 to -11
run, signalling sem an extra six times.

When the UI-process resumes, each=12, count=1 and sem has six
excessSignals.  Completing the do: adds process -12 to the run queue.
Then counts 2, 3, & 4 queues processes -13, -14 & -15 to run.  Counts
5, 6, 7, 8, 9, 10 consume the excessSignals without suspending, queing
processes -16, -17, -18, -19, -20, -21 to run.

At count=11, the UI-process suspends at the wait, and process -12
runs.  This signals the UI-process to be queued to run.  Processes -13
to -21 run, signalling sem an extra nine times.

ecetera...

btw, The delay doesn't make much difference to how the forked
processes interact with the main UI-process, since all forked
processes execute before the UI-process resumed. It just interleaves
the delay/signal tags rather than grouping them.


1 1+
2 2+
3 3+
4 4+
5 5+ wait
 1 5 delay
 2 5 delay
 3 5 delay
 4 5 delay
 1 4- signal
 2 3- signal
 3 2- signal
 4 1- signal
5 1 postwait, excessSignals 3
6 2+
7 3+
8 4+
9 5+ nowait
10 6+ nowait
11 7+ nowait
12 8+ wait
 5 8 delay
 6 8 delay
 7 8 delay
 8 8 delay
 9 8 delay
 10 8 delay
 11 8 delay
 5 7- signal
 6 6- signal
 7 5- signal
 8 4- signal
 9 3- signal
 10 2- signal
 11 1- signal
12 1 postwait, excessSignals 6
13 2+
14 3+
15 4+
16 5+ nowait
17 6+ nowait
18 7+ nowait
19 8+ nowait
20 9+ nowait
21 10+ nowait
22 11+ wait
 12 11 delay
 13 11 delay
 14 11 delay
 15 11 delay
 16 11 delay
 17 11 delay
 18 11 delay
 19 11 delay
 20 11 delay
 21 11 delay
 12 10- signal
 13 9- signal
 14 8- signal
 15 7- signal
 16 6- signal
 17 5- signal
 18 4- signal
 19 3- signal
 20 2- signal
 21 1- signal
22 1 postwait, excessSignals 9
23 2+
24 3+
25 4+
26 5+ nowait
27 6+ nowait
28 7+ nowait
29 8+ nowait
30 9+ nowait
31 10+ nowait
32 11+ nowait
33 12+ nowait
34 13+ nowait
35 14+ wait
 22 14 delay
 23 14 delay
 24 14 delay
 25 14 delay
 26 14 delay
 27 14 delay
 28 14 delay
 29 14 delay
 30 14 delay
 31 14 delay
 32 14 delay
 33 14 delay
 34 14 delay
 22 13- signal
 23 12- signal
 24 11- signal
 25 10- signal
 26 9- signal
 27 8- signal
 28 7- signal
 29 6- signal
 30 5- signal
 31 4- signal
 32 3- signal
 33 2- signal
 34 1- signal
35 1 postwait, excessSignals 12
36 2+
37 3+
38 4+
39 5+ nowait
40 6+ nowait
41 7+ nowait
42 8+ nowait
43 9+ nowait
44 10+ nowait
45 11+ nowait
46 12+ nowait
47 13+ nowait
48 14+ nowait
49 15+ nowait
50 16+ nowait
51 17+ wait
 35 17 delay
 36 17 delay
 37 17 delay
 38 17 delay
 39 17 delay
 40 17 delay
 41 17 delay
 42 17 delay
 43 17 delay
 44 17 delay
 45 17 delay
 46 17 delay
 47 17 delay
 48 17 delay
 49 17 delay
 50 17 delay
 35 16- signal
 36 15- signal
 37 14- signal
 38 13- signal
 39 12- signal
 40 11- signal
 41 10- signal
 42 9- signal
 43 8- signal
 44 7- signal
 45 6- signal
 46 5- signal
 47 4- signal
 48 3- signal
 49 2- signal
 50 1- signal
51 1 postwait, excessSignals 15
52 2+
53 3+
54 4+
55 5+ nowait
56 6+ nowait
57 7+ nowait
58 8+ nowait
59 9+ nowait
60 10+ nowait
61 11+ nowait
62 12+ nowait
63 13+ nowait
64 14+ nowait
65 15+ nowait
66 16+ nowait
67 17+ nowait
68 18+ nowait
69 19+ nowait
70 20+ wait
 51 20 delay
 52 20 delay
 53 20 delay
 54 20 delay
 55 20 delay
 56 20 delay
 57 20 delay
 58 20 delay
 59 20 delay
 60 20 delay
 61 20 delay
 62 20 delay
 63 20 delay
 64 20 delay
 65 20 delay
 66 20 delay
 67 20 delay
 68 20 delay
 69 20 delay
 51 19- signal
 52 18- signal
 53 17- signal
 54 16- signal
 55 15- signal
 56 14- signal
 57 13- signal
 58 12- signal
 59 11- signal
 60 10- signal
 61 9- signal
 62 8- signal
 63 7- signal
 64 6- signal
 65 5- signal
 66 4- signal
 67 3- signal
 68 2- signal
 69 1- signal
70 1 postwait, excessSignals 18
71 2+
72 3+
73 4+
74 5+ nowait
75 6+ nowait
76 7+ nowait
77 8+ nowait
78 9+ nowait
79 10+ nowait
80 11+ nowait
81 12+ nowait
82 13+ nowait
83 14+ nowait
84 15+ nowait
85 16+ nowait
86 17+ nowait
87 18+ nowait
88 19+ nowait
89 20+ nowait
90 21+ nowait
91 22+ nowait
92 23+ wait
 70 23 delay
 71 23 delay
 72 23 delay
 73 23 delay
 74 23 delay
 75 23 delay
 76 23 delay
 77 23 delay
 78 23 delay
 79 23 delay
 80 23 delay
 81 23 delay
 82 23 delay
 83 23 delay
 84 23 delay
 85 23 delay
 86 23 delay
 87 23 delay
 88 23 delay
 89 23 delay
 90 23 delay
 91 23 delay
 70 22- signal
 71 21- signal
 72 20- signal
 73 19- signal
 74 18- signal
 75 17- signal
 76 16- signal
 77 15- signal
 78 14- signal
 79 13- signal
 80 12- signal
 81 11- signal
 82 10- signal
 83 9- signal
 84 8- signal
 85 7- signal
 86 6- signal
 87 5- signal
 88 4- signal
 89 3- signal
 90 2- signal
 91 1- signal
92 1 postwait, excessSignals 21
93 2+
94 3+
95 4+
96 5+ nowait
97 6+ nowait
98 7+ nowait
99 8+ nowait
 92 8 delay
 93 8 delay
 94 8 delay
 95 8 delay
 96 8 delay
 97 8 delay
 98 8 delay
 99 8 delay
 92 7- signal
 93 6- signal
 94 5- signal
 95 4- signal
 96 3- signal
 97 2- signal
 98 1- signal
 99 0- signal

Reply | Threaded
Open this post in threaded view
|

Re: Semaphore wait and signal

Ben Coman
In reply to this post by vinref
On Tue, May 10, 2016 at 6:31 PM, Vince Refiti <[hidden email]> wrote:
> Hello
>
> I am playing around with Semaphore, and wrote the following:

[snip]

> Can someone please explain this pattern?

I rearranged again to make the output self explanatory...

  | coll count sem |
  Transcript clear; show: 'count' ; tab; show: 'each'.
  coll := Array withAll: (1 to: 99).
  count := 0.
  sem := Semaphore new.
  coll do:
  [   :each |
      count := count + 1.
      Transcript crShow: count printString; tab.
      (count >= 5) ifTrue:
          [ sem isSignaled
               ifTrue: [
                   Transcript tab; show: 'consumeExcess, nowait, '.
                    sem wait ]
               ifFalse: [
                  Transcript tab; show: 'main/UI waits on sem'.
                   sem wait.
                   Transcript cr; tab; tab;
                          show: 'main/UI runs, excessSignals ' ;
                          show: sem excessSignals printString; cr; tab. ]
           ].

     Transcript tab ; show: each printString, ' queued to run'.
      [    count := count -1.
           Transcript crShow: count printString; tab ; tab;
                      show: each printString,  ' runs, signals sem'.
            sem signal.
            sem isSignaled ifFalse: [  Transcript show: ', UI queued to run' ].
      ] fork.
  ]



On Tue, May 10, 2016 at 6:31 PM, Vince Refiti <[hidden email]> wrote:
> Hello
>
> I am playing around with Semaphore, and wrote the following:

[snip]

> Can someone please explain this pattern?

I rearranged again to make the output self explanatory...

  | coll count sem |
  Transcript clear; show: 'count' ; tab; show: 'each'.
  coll := Array withAll: (1 to: 99).
  count := 0.
  sem := Semaphore new.
  coll do:
  [   :each |
      count := count + 1.
      Transcript crShow: count printString; tab.
      (count >= 5) ifTrue:
          [ sem isSignaled
               ifTrue: [
                   Transcript tab; show: 'nowait '.
                    sem wait ]
               ifFalse: [
                  Transcript tab; show: 'main/UI waits on sem'.
                   sem wait.
                   Transcript cr; tab; tab;
                          show: 'main/UI runs, excessSignals ' ;
                          show: sem excessSignals printString; cr; tab. ]
           ].

     Transcript tab ; show: each printString, ' queued to run'.
      [    count := count -1.
           Transcript crShow: count printString; tab ; tab;
                      show: each printString,  ' runs, signals sem'.
            sem signal.
            sem isSignaled ifFalse: [  Transcript show: ', main/UI
queued to run' ].
      ] fork.
  ]


count each
1    1 queued to run
2    2 queued to run
3    3 queued to run
4    4 queued to run
5    main/UI waits on sem
4    1 runs, signals sem, main/UI queued to run
3    2 runs, signals sem
2    3 runs, signals sem
1    4 runs, signals sem
     main/UI runs, excessSignals 3
     5 queued to run
2    6 queued to run
3    7 queued to run
4    8 queued to run
5    consumeExcess, nowait, 9 queued to run
6    consumeExcess, nowait, 10 queued to run
7    consumeExcess, nowait, 11 queued to run
8    main/UI waits on sem
7    5 runs, signals sem, main/UI queued to run
6    6 runs, signals sem
5    7 runs, signals sem
4    8 runs, signals sem
3    9 runs, signals sem
2    10 runs, signals sem
1    11 runs, signals sem
     main/UI runs, excessSignals 6
     12 queued to run
2    13 queued to run
3    14 queued to run
4    15 queued to run
5    consumeExcess, nowait, 16 queued to run
6    consumeExcess, nowait, 17 queued to run
7    consumeExcess, nowait, 18 queued to run
8    consumeExcess, nowait, 19 queued to run
9    consumeExcess, nowait, 20 queued to run
10   consumeExcess, nowait, 21 queued to run
11   main/UI waits on sem
10   12 runs, signals sem, main/UI queued to run
9    13 runs, signals sem
8    14 runs, signals sem
7    15 runs, signals sem
6    16 runs, signals sem
5    17 runs, signals sem
4    18 runs, signals sem
3    19 runs, signals sem
2    20 runs, signals sem
1    21 runs, signals sem
     main/UI runs, excessSignals 9
     22 queued to run
2    23 queued to run
3    24 queued to run
4    25 queued to run
5    consumeExcess, nowait, 26 queued to run
6    consumeExcess, nowait, 27 queued to run
7    consumeExcess, nowait, 28 queued to run
8    consumeExcess, nowait, 29 queued to run
9    consumeExcess, nowait, 30 queued to run
10   consumeExcess, nowait, 31 queued to run
11   consumeExcess, nowait, 32 queued to run
12   consumeExcess, nowait, 33 queued to run
13   consumeExcess, nowait, 34 queued to run
14   main/UI waits on sem
13   22 runs, signals sem, main/UI queued to run
12   23 runs, signals sem
11   24 runs, signals sem
10   25 runs, signals sem
9    26 runs, signals sem
8    27 runs, signals sem
7    28 runs, signals sem
6    29 runs, signals sem
5    30 runs, signals sem
4    31 runs, signals sem
3    32 runs, signals sem
2    33 runs, signals sem
1    34 runs, signals sem
     main/UI runs, excessSignals 12
     35 queued to run
2    36 queued to run
3    37 queued to run
4    38 queued to run
5    consumeExcess, nowait, 39 queued to run
6    consumeExcess, nowait, 40 queued to run
7    consumeExcess, nowait, 41 queued to run
8    consumeExcess, nowait, 42 queued to run
9    consumeExcess, nowait, 43 queued to run
10   consumeExcess, nowait, 44 queued to run
11   consumeExcess, nowait, 45 queued to run
12   consumeExcess, nowait, 46 queued to run
13   consumeExcess, nowait, 47 queued to run
14   consumeExcess, nowait, 48 queued to run
15   consumeExcess, nowait, 49 queued to run
16   consumeExcess, nowait, 50 queued to run
17   main/UI waits on sem
16   35 runs, signals sem, main/UI queued to run
15   36 runs, signals sem
14   37 runs, signals sem
13   38 runs, signals sem
12   39 runs, signals sem
11   40 runs, signals sem
10   41 runs, signals sem
9    42 runs, signals sem
8    43 runs, signals sem
7    44 runs, signals sem
6    45 runs, signals sem
5    46 runs, signals sem
4    47 runs, signals sem
3    48 runs, signals sem
2    49 runs, signals sem
1    50 runs, signals sem
     main/UI runs, excessSignals 15
     51 queued to run
2    52 queued to run
3    53 queued to run
4    54 queued to run
5    consumeExcess, nowait, 55 queued to run
6    consumeExcess, nowait, 56 queued to run
7    consumeExcess, nowait, 57 queued to run
8    consumeExcess, nowait, 58 queued to run
9    consumeExcess, nowait, 59 queued to run
10   consumeExcess, nowait, 60 queued to run
11   consumeExcess, nowait, 61 queued to run
12   consumeExcess, nowait, 62 queued to run
13   consumeExcess, nowait, 63 queued to run
14   consumeExcess, nowait, 64 queued to run
15   consumeExcess, nowait, 65 queued to run
16   consumeExcess, nowait, 66 queued to run
17   consumeExcess, nowait, 67 queued to run
18   consumeExcess, nowait, 68 queued to run
19   consumeExcess, nowait, 69 queued to run
20   main/UI waits on sem
19   51 runs, signals sem, main/UI queued to run
18   52 runs, signals sem
17   53 runs, signals sem
16   54 runs, signals sem
15   55 runs, signals sem
14   56 runs, signals sem
13   57 runs, signals sem
12   58 runs, signals sem
11   59 runs, signals sem
10   60 runs, signals sem
9    61 runs, signals sem
8    62 runs, signals sem
7    63 runs, signals sem
6    64 runs, signals sem
5    65 runs, signals sem
4    66 runs, signals sem
3    67 runs, signals sem
2    68 runs, signals sem
1    69 runs, signals sem
     main/UI runs, excessSignals 18
     70 queued to run
2    71 queued to run
3    72 queued to run
4    73 queued to run
5    consumeExcess, nowait, 74 queued to run
6    consumeExcess, nowait, 75 queued to run
7    consumeExcess, nowait, 76 queued to run
8    consumeExcess, nowait, 77 queued to run
9    consumeExcess, nowait, 78 queued to run
10   consumeExcess, nowait, 79 queued to run
11   consumeExcess, nowait, 80 queued to run
12   consumeExcess, nowait, 81 queued to run
13   consumeExcess, nowait, 82 queued to run
14   consumeExcess, nowait, 83 queued to run
15   consumeExcess, nowait, 84 queued to run
16   consumeExcess, nowait, 85 queued to run
17   consumeExcess, nowait, 86 queued to run
18   consumeExcess, nowait, 87 queued to run
19   consumeExcess, nowait, 88 queued to run
20   consumeExcess, nowait, 89 queued to run
21   consumeExcess, nowait, 90 queued to run
22   consumeExcess, nowait, 91 queued to run
23   main/UI waits on sem
22   70 runs, signals sem, main/UI queued to run
21   71 runs, signals sem
20   72 runs, signals sem
19   73 runs, signals sem
18   74 runs, signals sem
17   75 runs, signals sem
16   76 runs, signals sem
15   77 runs, signals sem
14   78 runs, signals sem
13   79 runs, signals sem
12   80 runs, signals sem
11   81 runs, signals sem
10   82 runs, signals sem
9    83 runs, signals sem
8    84 runs, signals sem
7    85 runs, signals sem
6    86 runs, signals sem
5    87 runs, signals sem
4    88 runs, signals sem
3    89 runs, signals sem
2    90 runs, signals sem
1    91 runs, signals sem
     main/UI runs, excessSignals 21
     92 queued to run
2    93 queued to run
3    94 queued to run
4    95 queued to run
5    consumeExcess, nowait, 96 queued to run
6    consumeExcess, nowait, 97 queued to run
7    consumeExcess, nowait, 98 queued to run
8    consumeExcess, nowait, 99 queued to run
7    92 runs, signals sem
6    93 runs, signals sem
5    94 runs, signals sem
4    95 runs, signals sem
3    96 runs, signals sem
2    97 runs, signals sem
1    98 runs, signals sem
0    99 runs, signals sem

HTH,
cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: Semaphore wait and signal

stepharo
Superb email ben

We should really push a little tutorial on concurrent programming with
Pharo :)

Stef


Le 11/5/16 à 15:08, Ben Coman a écrit :

> On Tue, May 10, 2016 at 6:31 PM, Vince Refiti <[hidden email]> wrote:
>> Hello
>>
>> I am playing around with Semaphore, and wrote the following:
> [snip]
>
>> Can someone please explain this pattern?
> I rearranged again to make the output self explanatory...
>
>    | coll count sem |
>    Transcript clear; show: 'count' ; tab; show: 'each'.
>    coll := Array withAll: (1 to: 99).
>    count := 0.
>    sem := Semaphore new.
>    coll do:
>    [   :each |
>        count := count + 1.
>        Transcript crShow: count printString; tab.
>        (count >= 5) ifTrue:
>            [ sem isSignaled
>                 ifTrue: [
>                     Transcript tab; show: 'consumeExcess, nowait, '.
>                      sem wait ]
>                 ifFalse: [
>                    Transcript tab; show: 'main/UI waits on sem'.
>                     sem wait.
>                     Transcript cr; tab; tab;
>                            show: 'main/UI runs, excessSignals ' ;
>                            show: sem excessSignals printString; cr; tab. ]
>             ].
>
>       Transcript tab ; show: each printString, ' queued to run'.
>        [    count := count -1.
>             Transcript crShow: count printString; tab ; tab;
>                        show: each printString,  ' runs, signals sem'.
>              sem signal.
>              sem isSignaled ifFalse: [  Transcript show: ', UI queued to run' ].
>        ] fork.
>    ]
>
>
>
> On Tue, May 10, 2016 at 6:31 PM, Vince Refiti <[hidden email]> wrote:
>> Hello
>>
>> I am playing around with Semaphore, and wrote the following:
> [snip]
>
>> Can someone please explain this pattern?
> I rearranged again to make the output self explanatory...
>
>    | coll count sem |
>    Transcript clear; show: 'count' ; tab; show: 'each'.
>    coll := Array withAll: (1 to: 99).
>    count := 0.
>    sem := Semaphore new.
>    coll do:
>    [   :each |
>        count := count + 1.
>        Transcript crShow: count printString; tab.
>        (count >= 5) ifTrue:
>            [ sem isSignaled
>                 ifTrue: [
>                     Transcript tab; show: 'nowait '.
>                      sem wait ]
>                 ifFalse: [
>                    Transcript tab; show: 'main/UI waits on sem'.
>                     sem wait.
>                     Transcript cr; tab; tab;
>                            show: 'main/UI runs, excessSignals ' ;
>                            show: sem excessSignals printString; cr; tab. ]
>             ].
>
>       Transcript tab ; show: each printString, ' queued to run'.
>        [    count := count -1.
>             Transcript crShow: count printString; tab ; tab;
>                        show: each printString,  ' runs, signals sem'.
>              sem signal.
>              sem isSignaled ifFalse: [  Transcript show: ', main/UI
> queued to run' ].
>        ] fork.
>    ]
>
>
> count each
> 1    1 queued to run
> 2    2 queued to run
> 3    3 queued to run
> 4    4 queued to run
> 5    main/UI waits on sem
> 4    1 runs, signals sem, main/UI queued to run
> 3    2 runs, signals sem
> 2    3 runs, signals sem
> 1    4 runs, signals sem
>       main/UI runs, excessSignals 3
>       5 queued to run
> 2    6 queued to run
> 3    7 queued to run
> 4    8 queued to run
> 5    consumeExcess, nowait, 9 queued to run
> 6    consumeExcess, nowait, 10 queued to run
> 7    consumeExcess, nowait, 11 queued to run
> 8    main/UI waits on sem
> 7    5 runs, signals sem, main/UI queued to run
> 6    6 runs, signals sem
> 5    7 runs, signals sem
> 4    8 runs, signals sem
> 3    9 runs, signals sem
> 2    10 runs, signals sem
> 1    11 runs, signals sem
>       main/UI runs, excessSignals 6
>       12 queued to run
> 2    13 queued to run
> 3    14 queued to run
> 4    15 queued to run
> 5    consumeExcess, nowait, 16 queued to run
> 6    consumeExcess, nowait, 17 queued to run
> 7    consumeExcess, nowait, 18 queued to run
> 8    consumeExcess, nowait, 19 queued to run
> 9    consumeExcess, nowait, 20 queued to run
> 10   consumeExcess, nowait, 21 queued to run
> 11   main/UI waits on sem
> 10   12 runs, signals sem, main/UI queued to run
> 9    13 runs, signals sem
> 8    14 runs, signals sem
> 7    15 runs, signals sem
> 6    16 runs, signals sem
> 5    17 runs, signals sem
> 4    18 runs, signals sem
> 3    19 runs, signals sem
> 2    20 runs, signals sem
> 1    21 runs, signals sem
>       main/UI runs, excessSignals 9
>       22 queued to run
> 2    23 queued to run
> 3    24 queued to run
> 4    25 queued to run
> 5    consumeExcess, nowait, 26 queued to run
> 6    consumeExcess, nowait, 27 queued to run
> 7    consumeExcess, nowait, 28 queued to run
> 8    consumeExcess, nowait, 29 queued to run
> 9    consumeExcess, nowait, 30 queued to run
> 10   consumeExcess, nowait, 31 queued to run
> 11   consumeExcess, nowait, 32 queued to run
> 12   consumeExcess, nowait, 33 queued to run
> 13   consumeExcess, nowait, 34 queued to run
> 14   main/UI waits on sem
> 13   22 runs, signals sem, main/UI queued to run
> 12   23 runs, signals sem
> 11   24 runs, signals sem
> 10   25 runs, signals sem
> 9    26 runs, signals sem
> 8    27 runs, signals sem
> 7    28 runs, signals sem
> 6    29 runs, signals sem
> 5    30 runs, signals sem
> 4    31 runs, signals sem
> 3    32 runs, signals sem
> 2    33 runs, signals sem
> 1    34 runs, signals sem
>       main/UI runs, excessSignals 12
>       35 queued to run
> 2    36 queued to run
> 3    37 queued to run
> 4    38 queued to run
> 5    consumeExcess, nowait, 39 queued to run
> 6    consumeExcess, nowait, 40 queued to run
> 7    consumeExcess, nowait, 41 queued to run
> 8    consumeExcess, nowait, 42 queued to run
> 9    consumeExcess, nowait, 43 queued to run
> 10   consumeExcess, nowait, 44 queued to run
> 11   consumeExcess, nowait, 45 queued to run
> 12   consumeExcess, nowait, 46 queued to run
> 13   consumeExcess, nowait, 47 queued to run
> 14   consumeExcess, nowait, 48 queued to run
> 15   consumeExcess, nowait, 49 queued to run
> 16   consumeExcess, nowait, 50 queued to run
> 17   main/UI waits on sem
> 16   35 runs, signals sem, main/UI queued to run
> 15   36 runs, signals sem
> 14   37 runs, signals sem
> 13   38 runs, signals sem
> 12   39 runs, signals sem
> 11   40 runs, signals sem
> 10   41 runs, signals sem
> 9    42 runs, signals sem
> 8    43 runs, signals sem
> 7    44 runs, signals sem
> 6    45 runs, signals sem
> 5    46 runs, signals sem
> 4    47 runs, signals sem
> 3    48 runs, signals sem
> 2    49 runs, signals sem
> 1    50 runs, signals sem
>       main/UI runs, excessSignals 15
>       51 queued to run
> 2    52 queued to run
> 3    53 queued to run
> 4    54 queued to run
> 5    consumeExcess, nowait, 55 queued to run
> 6    consumeExcess, nowait, 56 queued to run
> 7    consumeExcess, nowait, 57 queued to run
> 8    consumeExcess, nowait, 58 queued to run
> 9    consumeExcess, nowait, 59 queued to run
> 10   consumeExcess, nowait, 60 queued to run
> 11   consumeExcess, nowait, 61 queued to run
> 12   consumeExcess, nowait, 62 queued to run
> 13   consumeExcess, nowait, 63 queued to run
> 14   consumeExcess, nowait, 64 queued to run
> 15   consumeExcess, nowait, 65 queued to run
> 16   consumeExcess, nowait, 66 queued to run
> 17   consumeExcess, nowait, 67 queued to run
> 18   consumeExcess, nowait, 68 queued to run
> 19   consumeExcess, nowait, 69 queued to run
> 20   main/UI waits on sem
> 19   51 runs, signals sem, main/UI queued to run
> 18   52 runs, signals sem
> 17   53 runs, signals sem
> 16   54 runs, signals sem
> 15   55 runs, signals sem
> 14   56 runs, signals sem
> 13   57 runs, signals sem
> 12   58 runs, signals sem
> 11   59 runs, signals sem
> 10   60 runs, signals sem
> 9    61 runs, signals sem
> 8    62 runs, signals sem
> 7    63 runs, signals sem
> 6    64 runs, signals sem
> 5    65 runs, signals sem
> 4    66 runs, signals sem
> 3    67 runs, signals sem
> 2    68 runs, signals sem
> 1    69 runs, signals sem
>       main/UI runs, excessSignals 18
>       70 queued to run
> 2    71 queued to run
> 3    72 queued to run
> 4    73 queued to run
> 5    consumeExcess, nowait, 74 queued to run
> 6    consumeExcess, nowait, 75 queued to run
> 7    consumeExcess, nowait, 76 queued to run
> 8    consumeExcess, nowait, 77 queued to run
> 9    consumeExcess, nowait, 78 queued to run
> 10   consumeExcess, nowait, 79 queued to run
> 11   consumeExcess, nowait, 80 queued to run
> 12   consumeExcess, nowait, 81 queued to run
> 13   consumeExcess, nowait, 82 queued to run
> 14   consumeExcess, nowait, 83 queued to run
> 15   consumeExcess, nowait, 84 queued to run
> 16   consumeExcess, nowait, 85 queued to run
> 17   consumeExcess, nowait, 86 queued to run
> 18   consumeExcess, nowait, 87 queued to run
> 19   consumeExcess, nowait, 88 queued to run
> 20   consumeExcess, nowait, 89 queued to run
> 21   consumeExcess, nowait, 90 queued to run
> 22   consumeExcess, nowait, 91 queued to run
> 23   main/UI waits on sem
> 22   70 runs, signals sem, main/UI queued to run
> 21   71 runs, signals sem
> 20   72 runs, signals sem
> 19   73 runs, signals sem
> 18   74 runs, signals sem
> 17   75 runs, signals sem
> 16   76 runs, signals sem
> 15   77 runs, signals sem
> 14   78 runs, signals sem
> 13   79 runs, signals sem
> 12   80 runs, signals sem
> 11   81 runs, signals sem
> 10   82 runs, signals sem
> 9    83 runs, signals sem
> 8    84 runs, signals sem
> 7    85 runs, signals sem
> 6    86 runs, signals sem
> 5    87 runs, signals sem
> 4    88 runs, signals sem
> 3    89 runs, signals sem
> 2    90 runs, signals sem
> 1    91 runs, signals sem
>       main/UI runs, excessSignals 21
>       92 queued to run
> 2    93 queued to run
> 3    94 queued to run
> 4    95 queued to run
> 5    consumeExcess, nowait, 96 queued to run
> 6    consumeExcess, nowait, 97 queued to run
> 7    consumeExcess, nowait, 98 queued to run
> 8    consumeExcess, nowait, 99 queued to run
> 7    92 runs, signals sem
> 6    93 runs, signals sem
> 5    94 runs, signals sem
> 4    95 runs, signals sem
> 3    96 runs, signals sem
> 2    97 runs, signals sem
> 1    98 runs, signals sem
> 0    99 runs, signals sem
>
> HTH,
> cheers -ben
>
>