|
1 " |
|
2 COPYRIGHT (c) 1993 by Claus Gittinger |
|
3 All Rights Reserved |
|
4 |
|
5 This software is furnished under a license and may be used |
|
6 only in accordance with the terms of that license and with the |
|
7 inclusion of the above copyright notice. This software may not |
|
8 be provided or otherwise made available to, or used by, any |
|
9 other person. No title to or ownership of the software is |
|
10 hereby transferred. |
|
11 " |
|
12 |
|
13 LinkedList subclass:#Semaphore |
|
14 instanceVariableNames:'count waitingProcesses' |
|
15 classVariableNames:'' |
|
16 poolDictionaries:'' |
|
17 category:'Kernel-Processes'! |
|
18 |
|
19 Semaphore comment:' |
|
20 |
|
21 COPYRIGHT (c) 1993 by Claus Gittinger |
|
22 All Rights Reserved |
|
23 |
|
24 Semaphores are used to synchronize processes providing a nonBusy wait |
|
25 mechanism. A process can wait for the availability of some resource by |
|
26 performing a Semaphore-wait, which will suspend the process until the |
|
27 resource becomes available which is signalled by (another process performing) |
|
28 Semaphore-signal. |
|
29 If the resource has been alrady available before the wait, no suspending is |
|
30 done, but the resource immediately allocated. |
|
31 |
|
32 See samples in doc/coding. |
|
33 |
|
34 %W% %E% |
|
35 '! |
|
36 |
|
37 !Semaphore class methodsFor:'instance creation'! |
|
38 |
|
39 new |
|
40 "create & return a new semaphore which blocks until a signal is sent" |
|
41 |
|
42 ^ super new setCount:0 |
|
43 ! |
|
44 |
|
45 new:n |
|
46 "create & return a new semaphore which allows n waits before |
|
47 blocking" |
|
48 |
|
49 ^ super new setCount:n |
|
50 ! |
|
51 |
|
52 forMutualExclusion |
|
53 "create & return a new semaphore which allows exactly one process to |
|
54 wait on it without blocking" |
|
55 |
|
56 ^ self new:1 |
|
57 ! ! |
|
58 |
|
59 !Semaphore methodsFor:'private accessing'! |
|
60 |
|
61 setCount:n |
|
62 count := n |
|
63 ! ! |
|
64 |
|
65 !Semaphore methodsFor:'wait & signal'! |
|
66 |
|
67 wait |
|
68 "wait for the semaphore" |
|
69 |
|
70 |current| |
|
71 |
|
72 " |
|
73 need a while-loop here, since more than one process may |
|
74 wait for it and another one may also wake up. |
|
75 Thus count is not always non-zero after returning from |
|
76 suspend. |
|
77 " |
|
78 |
|
79 [count == 0] whileTrue:[ |
|
80 current := Processor currentProcess. |
|
81 waitingProcesses isNil ifTrue:[ |
|
82 waitingProcesses := OrderedCollection with:current |
|
83 ] ifFalse:[ |
|
84 waitingProcesses add:current |
|
85 ]. |
|
86 current suspend |
|
87 ]. |
|
88 count := count - 1 |
|
89 ! |
|
90 |
|
91 signal |
|
92 "waking up waiters" |
|
93 |
|
94 count := count + 1. |
|
95 waitingProcesses notNil ifTrue:[ |
|
96 waitingProcesses isEmpty ifFalse:[ |
|
97 waitingProcesses removeFirst resume |
|
98 ] |
|
99 ] |
|
100 ! |
|
101 |
|
102 critical:aBlock |
|
103 "evaluate aBlock as a critical region; the receiver must be |
|
104 created using Semaphore-forMutualExclusion" |
|
105 |
|
106 |value| |
|
107 |
|
108 self wait. |
|
109 value := aBlock value. |
|
110 self signal. |
|
111 ^ value |
|
112 ! ! |