55 under some condition. |
55 under some condition. |
56 See 'Processor>>signal:afterSeconds:', 'Processor>>signal:onInput:' etc. |
56 See 'Processor>>signal:afterSeconds:', 'Processor>>signal:onInput:' etc. |
57 |
57 |
58 See examples in doc/coding (found in the CodingExamples-nameSpace). |
58 See examples in doc/coding (found in the CodingExamples-nameSpace). |
59 |
59 |
|
60 Warning/Note/Hint: |
|
61 a Semaphore-forMutualExclusion does NEVER allow for the critical |
|
62 region to be entered twice - NOT EVEN by the same process. |
|
63 That means, that a recursive attempt to enter that section leads |
|
64 to a deadlock. |
|
65 Use a RecursionLock instead of a semaphore to avoid this. |
|
66 |
|
67 |
60 [instance variables:] |
68 [instance variables:] |
61 count <SmallInteger> the number of waits, that will go through |
69 count <SmallInteger> the number of waits, that will go through |
62 without blocking. |
70 without blocking. |
63 Incremented on #signal; decremented on #wait. |
71 Incremented on #signal; decremented on #wait. |
64 |
72 |
65 waitingProcesses <OrderedCollection> waiting processes - will be served first |
73 waitingProcesses <OrderedCollection> waiting processes - will be served first |
66 come first served when signalled. |
74 come first served when signalled. |
67 |
75 |
68 lastOwnerID <SmallInteger> a debugging aid: set when count drops |
76 lastOwnerID <SmallInteger> a debugging aid: set when count drops |
69 to zero to the current processes id. |
77 to zero to the current processes id. |
70 Helps in finding deadlocks. |
78 Helps in finding deadlocks. |
71 |
79 |
72 name <String> a debugging aid: an optional userFriendly |
80 name <String> a debugging aid: an optional userFriendly |
73 name; helps to identify a semaphore easier. |
81 name; helps to identify a semaphore easier. |
74 |
82 |
75 [see also:] |
83 [see also:] |
76 SemaphoreSet RecursionLock Monitor |
84 SemaphoreSet RecursionLock Monitor |
77 SharedQueue Delay |
85 SharedQueue Delay |
78 Process ProcessorScheduler |
86 Process ProcessorScheduler |
79 |
87 |
80 [author:] |
88 [author:] |
81 Claus Gittinger |
89 Claus Gittinger |
82 " |
90 " |
83 ! |
91 ! |
84 |
92 |
85 examples |
93 examples |
86 " |
94 " |
87 two processes synchronizing on a sema: |
95 two processes synchronizing on a sema: |
88 [exBegin] |
96 [exBegin] |
89 |sema thread1 thread2| |
97 |sema thread1 thread2| |
90 |
98 |
91 sema := Semaphore new. |
99 sema := Semaphore new. |
92 |
100 |
93 thread1 := [ |
101 thread1 := [ |
94 Transcript showCR:'here is thread 1; now waiting ...'. |
102 Transcript showCR:'here is thread 1; now waiting ...'. |
95 sema wait. |
103 sema wait. |
96 Transcript showCR:'here is thread 1 again.'. |
104 Transcript showCR:'here is thread 1 again.'. |
97 ] newProcess. |
105 ] newProcess. |
98 |
106 |
99 thread2 := [ |
107 thread2 := [ |
100 Transcript showCR:'here is thread 2; delaying a bit ...'. |
108 Transcript showCR:'here is thread 2; delaying a bit ...'. |
101 Delay waitForSeconds:5. |
109 Delay waitForSeconds:5. |
102 Transcript showCR:'here is thread 2 again; now signalling the sema'. |
110 Transcript showCR:'here is thread 2 again; now signalling the sema'. |
103 sema signal. |
111 sema signal. |
104 Transcript showCR:'here is thread 2 after the signalling.'. |
112 Transcript showCR:'here is thread 2 after the signalling.'. |
105 ] newProcess. |
113 ] newProcess. |
106 |
114 |
107 thread1 priority:7. |
115 thread1 priority:7. |
108 thread2 priority:6. |
116 thread2 priority:6. |
109 |
117 |
110 thread1 resume. |
118 thread1 resume. |
111 thread2 resume. |
119 thread2 resume. |
112 [exEnd] |
120 [exEnd] |
113 |
121 |
114 semaphore for critical regions: |
122 semaphore for critical regions: |
115 [exBegin] |
123 [exBegin] |
116 |accessLock| |
124 |accessLock| |
117 |
125 |
118 accessLock := Semaphore forMutualExclusion. |
126 accessLock := Semaphore forMutualExclusion. |
119 |
127 |
120 [ |
128 [ |
121 5 timesRepeat:[ |
129 5 timesRepeat:[ |
122 Delay waitForSeconds:2. |
130 Delay waitForSeconds:2. |
123 accessLock critical:[ |
131 accessLock critical:[ |
124 Transcript showCR:'thread1 in critical region'. |
132 Transcript showCR:'thread1 in critical region'. |
125 Delay waitForSeconds:1. |
133 Delay waitForSeconds:1. |
126 Transcript showCR:'thread1 leaving critical region'. |
134 Transcript showCR:'thread1 leaving critical region'. |
127 ]. |
135 ]. |
128 ] |
136 ] |
129 ] forkAt:5. |
137 ] forkAt:5. |
130 |
138 |
131 [ |
139 [ |
132 5 timesRepeat:[ |
140 5 timesRepeat:[ |
133 Delay waitForSeconds:1. |
141 Delay waitForSeconds:1. |
134 accessLock critical:[ |
142 accessLock critical:[ |
135 Transcript showCR:'thread2 in critical region'. |
143 Transcript showCR:'thread2 in critical region'. |
136 Delay waitForSeconds:2. |
144 Delay waitForSeconds:2. |
137 Transcript showCR:'thread2 leaving critical region'. |
145 Transcript showCR:'thread2 leaving critical region'. |
138 ]. |
146 ]. |
139 ] |
147 ] |
140 ] forkAt:4. |
148 ] forkAt:4. |
141 [exEnd] |
149 [exEnd] |
|
150 |
|
151 a deadlock due to recursive enter of a critical region: |
|
152 [exBegin] |
|
153 |accessLock block| |
|
154 |
|
155 accessLock := Semaphore forMutualExclusion. |
|
156 |
|
157 block := [:arg | |
|
158 Transcript showCR:'about to enter'. |
|
159 accessLock critical:[ |
|
160 Transcript showCR:'entered - doing action'. |
|
161 arg value |
|
162 ]. |
|
163 Transcript showCR:'left region'. |
|
164 ]. |
|
165 |
|
166 block value:[]. 'this works'. |
|
167 block value:[block value:[] ]. 'this deadlocks'. |
|
168 [exEnd] |
|
169 |
|
170 Avoid the deadlock by using a RecursionLock instead: |
|
171 [exBegin] |
|
172 |accessLock block| |
|
173 |
|
174 accessLock := RecursionLock new. |
|
175 |
|
176 block := [:arg | |
|
177 Transcript showCR:'about to enter'. |
|
178 accessLock critical:[ |
|
179 Transcript showCR:'entered - doing action'. |
|
180 arg value |
|
181 ]. |
|
182 Transcript showCR:'left region'. |
|
183 ]. |
|
184 |
|
185 block value:[]. 'this works'. |
|
186 block value:[block value:[] ]. 'this deadlocks'. |
|
187 [exEnd] |
142 " |
188 " |
143 ! ! |
189 ! ! |
144 |
190 |
145 !Semaphore class methodsFor:'instance creation'! |
191 !Semaphore class methodsFor:'instance creation'! |
146 |
192 |
147 forMutualExclusion |
193 forMutualExclusion |
148 "create & return a new semaphore which allows exactly one process to |
194 "create & return a new semaphore which allows exactly one process to |
149 wait on it without blocking. This type of semaphore is used |
195 wait on it without blocking. This type of semaphore is used |
150 for mutual exclusion from critical regions (see #critical:)" |
196 for mutual exclusion from critical regions (see #critical:). |
|
197 Also see RecursionLock, to avoid deadlock in case of recursive entered |
|
198 critical regions." |
151 |
199 |
152 ^ super new setCount:1; name:'criticalRegionSema' |
200 ^ super new setCount:1; name:'criticalRegionSema' |
153 |
201 |
154 "Modified: / 17.6.1998 / 16:23:09 / cg" |
202 "Modified: / 17.6.1998 / 16:23:09 / cg" |
155 ! |
203 ! |