93 if a wait was performed. False otherwise." |
96 if a wait was performed. False otherwise." |
94 |
97 |
95 ^ count == 0 |
98 ^ count == 0 |
96 ! ! |
99 ! ! |
97 |
100 |
98 !Semaphore methodsFor:'printing & storing'! |
|
99 |
|
100 displayString |
|
101 ^ self class name , '(' , count printString , ')' |
|
102 ! ! |
|
103 |
|
104 !Semaphore methodsFor:'wait & signal'! |
101 !Semaphore methodsFor:'wait & signal'! |
105 |
|
106 wait |
|
107 "wait for the semaphore" |
|
108 |
|
109 |current wasBlocked| |
|
110 |
|
111 " |
|
112 this works only since interrupts are only serviced at |
|
113 message send and method-return time .... |
|
114 If you add a message send into the ifTrue:-block, things will |
|
115 go mad ... (especially be careful when adding a debugPrint-here) |
|
116 " |
|
117 count ~~ 0 ifTrue:[ |
|
118 count := count - 1. |
|
119 ^ self |
|
120 ]. |
|
121 |
|
122 current := Processor activeProcess. |
|
123 |
|
124 wasBlocked := OperatingSystem blockInterrupts. |
|
125 " |
|
126 need a while-loop here, since more than one process may |
|
127 wait for it and another one may also wake up. |
|
128 Thus, the count is not always non-zero after returning from |
|
129 suspend. |
|
130 " |
|
131 [count == 0] whileTrue:[ |
|
132 waitingProcesses add:current. |
|
133 " |
|
134 for some more descriptive info in processMonitor ... |
|
135 (notice that state could already be #ioWait, #timeWait or anything else) |
|
136 " |
|
137 current setStateTo:#wait if:#active. |
|
138 Processor suspend:current |
|
139 ]. |
|
140 count := count - 1. |
|
141 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
142 ! |
|
143 |
|
144 waitUncounted |
|
145 "wait for the semaphore; do not consume the resource |
|
146 (i.e. do not count down)" |
|
147 |
|
148 |current wasBlocked| |
|
149 |
|
150 " |
|
151 this works only since interrupts are only serviced at |
|
152 message send and method-return time .... |
|
153 If you add a message send into the ifTrue:-block, things will |
|
154 go mad ... (especially be careful when adding a debugPrint-here) |
|
155 " |
|
156 count ~~ 0 ifTrue:[ |
|
157 ^ self |
|
158 ]. |
|
159 |
|
160 current := Processor activeProcess. |
|
161 |
|
162 wasBlocked := OperatingSystem blockInterrupts. |
|
163 " |
|
164 need a while-loop here, since more than one process may |
|
165 wait for it and another one may also wake up. |
|
166 Thus, the count is not always non-zero after returning from |
|
167 suspend. |
|
168 " |
|
169 [count == 0] whileTrue:[ |
|
170 waitingProcesses add:current. |
|
171 " |
|
172 for some more descriptive info in processMonitor ... |
|
173 (notice that state could already be #ioWait, #timeWait or anything else) |
|
174 " |
|
175 current setStateTo:#wait if:#active. |
|
176 Processor suspend:current |
|
177 ]. |
|
178 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
179 ! |
|
180 |
|
181 waitWithTimeout:seconds |
|
182 "wait for the semaphore, but abort the wait after some time. |
|
183 return true if semaphore triggered normal, false if we return |
|
184 due to a timeout. With zero timeout, this can be used to poll |
|
185 a semaphore (which is not the intend of semaphores, though)." |
|
186 |
|
187 |current timeoutOccured wasBlocked unblock now endTime| |
|
188 |
|
189 " |
|
190 this works only since interrupts are only serviced at |
|
191 message send and method-return time .... |
|
192 If you add a message send into the ifTrue:-block, things will |
|
193 go mad ... (especially be careful when adding a debugPrint-here) |
|
194 " |
|
195 count ~~ 0 ifTrue:[ |
|
196 count := count - 1. |
|
197 ^ true |
|
198 ]. |
|
199 |
|
200 " |
|
201 with zero-timeout, this is a poll |
|
202 " |
|
203 seconds = 0 ifTrue:[ |
|
204 ^ false |
|
205 ]. |
|
206 |
|
207 current := Processor activeProcess. |
|
208 |
|
209 wasBlocked := OperatingSystem blockInterrupts. |
|
210 |
|
211 " |
|
212 calculate the end-time |
|
213 " |
|
214 now := OperatingSystem getMillisecondTime. |
|
215 endTime := OperatingSystem millisecondTimeAdd:now and:(seconds * 1000). |
|
216 |
|
217 unblock := [timeoutOccured := true. Processor resume:current]. |
|
218 Processor addTimedBlock:unblock for:current atMilliseconds:endTime. |
|
219 |
|
220 " |
|
221 need a while-loop here, since more than one process may |
|
222 wait for it and another one may also wake up. |
|
223 Thus, the count is not always non-zero after returning from |
|
224 suspend. |
|
225 " |
|
226 [count == 0] whileTrue:[ |
|
227 waitingProcesses add:current. |
|
228 |
|
229 " |
|
230 for some more descriptive info in processMonitor ... |
|
231 (notice that state could already be #ioWait or #timeWait) |
|
232 " |
|
233 current setStateTo:#wait if:#active. |
|
234 |
|
235 timeoutOccured := false. |
|
236 Processor suspend:current. |
|
237 |
|
238 timeoutOccured ifTrue:[ |
|
239 waitingProcesses remove:current ifAbsent:[]. |
|
240 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
241 ^ false |
|
242 ]. |
|
243 ]. |
|
244 Processor removeTimedBlock:unblock. |
|
245 count := count - 1. |
|
246 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
247 ^ true |
|
248 ! |
|
249 |
|
250 signalOnce |
|
251 "wakeup waiters - but only once. |
|
252 I.e. if the semaphore has already been signalled, this |
|
253 is ignored." |
|
254 |
|
255 |wasBlocked| |
|
256 |
|
257 count == 0 ifTrue:[ |
|
258 wasBlocked := OperatingSystem blockInterrupts. |
|
259 count == 0 ifTrue:[ |
|
260 self signal |
|
261 ]. |
|
262 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
263 ] |
|
264 ! |
|
265 |
|
266 signal |
|
267 "waking up (first) waiter" |
|
268 |
|
269 |p wasBlocked| |
|
270 |
|
271 wasBlocked := OperatingSystem blockInterrupts. |
|
272 count := count + 1. |
|
273 waitingProcesses notEmpty ifTrue:[ |
|
274 p := waitingProcesses removeFirst. |
|
275 p resume. |
|
276 ]. |
|
277 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
278 ! |
|
279 |
|
280 signalIf |
|
281 "signal the semaphore, but only if being waited upon. |
|
282 This can be used for one-shot semaphores (i.e. not remembering |
|
283 previous signals)" |
|
284 |
|
285 |wasBlocked| |
|
286 |
|
287 waitingProcesses notEmpty ifTrue:[ |
|
288 wasBlocked := OperatingSystem blockInterrupts. |
|
289 waitingProcesses notEmpty ifTrue:[ |
|
290 self signal |
|
291 ]. |
|
292 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
293 ] |
|
294 ! |
|
295 |
|
296 signalForAll |
|
297 "signal the semaphore for all waiters. |
|
298 This can be used for process synchronization, if multiple processes are |
|
299 waiting for a common event." |
|
300 |
|
301 |wasBlocked| |
|
302 |
|
303 [waitingProcesses notEmpty] whileTrue:[ |
|
304 wasBlocked := OperatingSystem blockInterrupts. |
|
305 waitingProcesses notEmpty ifTrue:[ |
|
306 self signal |
|
307 ]. |
|
308 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
309 ] |
|
310 ! |
|
311 |
102 |
312 critical:aBlock |
103 critical:aBlock |
313 "evaluate aBlock as a critical region; the receiver must be |
104 "evaluate aBlock as a critical region; the receiver must be |
314 created using Semaphore>>forMutualExclusion" |
105 created using Semaphore>>forMutualExclusion" |
315 |
106 |
343 (Delay forSeconds:0.1) wait. |
134 (Delay forSeconds:0.1) wait. |
344 ] |
135 ] |
345 ] |
136 ] |
346 ] forkAt:4. |
137 ] forkAt:4. |
347 " |
138 " |
348 ! ! |
139 ! |
|
140 |
|
141 signal |
|
142 "waking up (first) waiter" |
|
143 |
|
144 |p wasBlocked| |
|
145 |
|
146 wasBlocked := OperatingSystem blockInterrupts. |
|
147 count := count + 1. |
|
148 waitingProcesses notEmpty ifTrue:[ |
|
149 p := waitingProcesses removeFirst. |
|
150 p resume. |
|
151 ]. |
|
152 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
153 ! |
|
154 |
|
155 signalForAll |
|
156 "signal the semaphore for all waiters. |
|
157 This can be used for process synchronization, if multiple processes are |
|
158 waiting for a common event." |
|
159 |
|
160 |wasBlocked| |
|
161 |
|
162 [waitingProcesses notEmpty] whileTrue:[ |
|
163 wasBlocked := OperatingSystem blockInterrupts. |
|
164 waitingProcesses notEmpty ifTrue:[ |
|
165 self signal |
|
166 ]. |
|
167 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
168 ] |
|
169 ! |
|
170 |
|
171 signalIf |
|
172 "signal the semaphore, but only if being waited upon. |
|
173 This can be used for one-shot semaphores (i.e. not remembering |
|
174 previous signals)" |
|
175 |
|
176 |wasBlocked| |
|
177 |
|
178 waitingProcesses notEmpty ifTrue:[ |
|
179 wasBlocked := OperatingSystem blockInterrupts. |
|
180 waitingProcesses notEmpty ifTrue:[ |
|
181 self signal |
|
182 ]. |
|
183 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
184 ] |
|
185 ! |
|
186 |
|
187 signalOnce |
|
188 "wakeup waiters - but only once. |
|
189 I.e. if the semaphore has already been signalled, this |
|
190 is ignored." |
|
191 |
|
192 |wasBlocked| |
|
193 |
|
194 count == 0 ifTrue:[ |
|
195 wasBlocked := OperatingSystem blockInterrupts. |
|
196 count == 0 ifTrue:[ |
|
197 self signal |
|
198 ]. |
|
199 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
200 ] |
|
201 ! |
|
202 |
|
203 wait |
|
204 "wait for the semaphore" |
|
205 |
|
206 |current wasBlocked| |
|
207 |
|
208 " |
|
209 this works only since interrupts are only serviced at |
|
210 message send and method-return time .... |
|
211 If you add a message send into the ifTrue:-block, things will |
|
212 go mad ... (especially be careful when adding a debugPrint-here) |
|
213 " |
|
214 count ~~ 0 ifTrue:[ |
|
215 count := count - 1. |
|
216 ^ self |
|
217 ]. |
|
218 |
|
219 current := Processor activeProcess. |
|
220 |
|
221 wasBlocked := OperatingSystem blockInterrupts. |
|
222 " |
|
223 need a while-loop here, since more than one process may |
|
224 wait for it and another one may also wake up. |
|
225 Thus, the count is not always non-zero after returning from |
|
226 suspend. |
|
227 " |
|
228 [count == 0] whileTrue:[ |
|
229 waitingProcesses add:current. |
|
230 " |
|
231 for some more descriptive info in processMonitor ... |
|
232 (notice that state could already be #ioWait, #timeWait or anything else) |
|
233 " |
|
234 current setStateTo:#wait if:#active. |
|
235 Processor suspend:current |
|
236 ]. |
|
237 count := count - 1. |
|
238 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
239 ! |
|
240 |
|
241 waitUncounted |
|
242 "wait for the semaphore; do not consume the resource |
|
243 (i.e. do not count down)" |
|
244 |
|
245 |current wasBlocked| |
|
246 |
|
247 " |
|
248 this works only since interrupts are only serviced at |
|
249 message send and method-return time .... |
|
250 If you add a message send into the ifTrue:-block, things will |
|
251 go mad ... (especially be careful when adding a debugPrint-here) |
|
252 " |
|
253 count ~~ 0 ifTrue:[ |
|
254 ^ self |
|
255 ]. |
|
256 |
|
257 current := Processor activeProcess. |
|
258 |
|
259 wasBlocked := OperatingSystem blockInterrupts. |
|
260 " |
|
261 need a while-loop here, since more than one process may |
|
262 wait for it and another one may also wake up. |
|
263 Thus, the count is not always non-zero after returning from |
|
264 suspend. |
|
265 " |
|
266 [count == 0] whileTrue:[ |
|
267 waitingProcesses add:current. |
|
268 " |
|
269 for some more descriptive info in processMonitor ... |
|
270 (notice that state could already be #ioWait, #timeWait or anything else) |
|
271 " |
|
272 current setStateTo:#wait if:#active. |
|
273 Processor suspend:current |
|
274 ]. |
|
275 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
276 ! |
|
277 |
|
278 waitWithTimeout:seconds |
|
279 "wait for the semaphore, but abort the wait after some time. |
|
280 return true if semaphore triggered normal, false if we return |
|
281 due to a timeout. With zero timeout, this can be used to poll |
|
282 a semaphore (which is not the intend of semaphores, though)." |
|
283 |
|
284 |current timeoutOccured wasBlocked unblock now endTime| |
|
285 |
|
286 " |
|
287 this works only since interrupts are only serviced at |
|
288 message send and method-return time .... |
|
289 If you add a message send into the ifTrue:-block, things will |
|
290 go mad ... (especially be careful when adding a debugPrint-here) |
|
291 " |
|
292 count ~~ 0 ifTrue:[ |
|
293 count := count - 1. |
|
294 ^ true |
|
295 ]. |
|
296 |
|
297 " |
|
298 with zero-timeout, this is a poll |
|
299 " |
|
300 seconds = 0 ifTrue:[ |
|
301 ^ false |
|
302 ]. |
|
303 |
|
304 current := Processor activeProcess. |
|
305 |
|
306 wasBlocked := OperatingSystem blockInterrupts. |
|
307 |
|
308 " |
|
309 calculate the end-time |
|
310 " |
|
311 now := OperatingSystem getMillisecondTime. |
|
312 endTime := OperatingSystem millisecondTimeAdd:now and:(seconds * 1000). |
|
313 |
|
314 unblock := [timeoutOccured := true. Processor resume:current]. |
|
315 Processor addTimedBlock:unblock for:current atMilliseconds:endTime. |
|
316 |
|
317 " |
|
318 need a while-loop here, since more than one process may |
|
319 wait for it and another one may also wake up. |
|
320 Thus, the count is not always non-zero after returning from |
|
321 suspend. |
|
322 " |
|
323 [count == 0] whileTrue:[ |
|
324 waitingProcesses add:current. |
|
325 |
|
326 " |
|
327 for some more descriptive info in processMonitor ... |
|
328 (notice that state could already be #ioWait or #timeWait) |
|
329 " |
|
330 current setStateTo:#wait if:#active. |
|
331 |
|
332 timeoutOccured := false. |
|
333 Processor suspend:current. |
|
334 |
|
335 timeoutOccured ifTrue:[ |
|
336 waitingProcesses remove:current ifAbsent:[]. |
|
337 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
338 ^ false |
|
339 ]. |
|
340 ]. |
|
341 Processor removeTimedBlock:unblock. |
|
342 count := count - 1. |
|
343 wasBlocked ifFalse:[OperatingSystem unblockInterrupts]. |
|
344 ^ true |
|
345 ! ! |
|
346 |
|
347 !Semaphore class methodsFor:'documentation'! |
|
348 |
|
349 version |
|
350 ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.24 1995-12-07 21:30:36 cg Exp $' |
|
351 ! ! |