"
COPYRIGHT (c) 1993 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
LinkedList subclass:#Semaphore
instanceVariableNames:'count waitingProcesses'
classVariableNames:''
poolDictionaries:''
category:'Kernel-Processes'!
Semaphore comment:'
COPYRIGHT (c) 1993 by Claus Gittinger
All Rights Reserved
'!
!Semaphore class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1993 by Claus Gittinger
All Rights Reserved
This software is furnished under a license and may be used
only in accordance with the terms of that license and with the
inclusion of the above copyright notice. This software may not
be provided or otherwise made available to, or used by, any
other person. No title to or ownership of the software is
hereby transferred.
"
!
version
"
$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.10 1994-06-02 16:21:53 claus Exp $
"
!
documentation
"
Semaphores are used to synchronize processes providing a nonBusy wait
mechanism. A process can wait for the availability of some resource by
performing a Semaphore-wait, which will suspend the process until the
resource becomes available which is signalled by
(another process performing) Semaphore-signal.
If the resource has been alrady available before the wait, no suspending is
done, but the resource immediately allocated.
There are also semaphores for mutual access of a critical region.
See examples in doc/coding.
"
! !
!Semaphore class methodsFor:'instance creation'!
new
"create & return a new semaphore which blocks until a signal is sent"
^ super new setCount:0
!
new:n
"create & return a new semaphore which allows n waits before
blocking"
^ super new setCount:n
!
forMutualExclusion
"create & return a new semaphore which allows exactly one process to
wait on it without blocking"
^ self new:1
! !
!Semaphore methodsFor:'private accessing'!
setCount:n
count := n
! !
!Semaphore methodsFor:'wait & signal'!
wait
"wait for the semaphore"
|current|
"
need a while-loop here, since more than one process may
wait for it and another one may also wake up.
Thus, the count is not always non-zero after returning from
suspend.
"
OperatingSystem blockInterrupts.
[count == 0] whileTrue:[
(count == 0) ifTrue:[
current := Processor activeProcess.
waitingProcesses isNil ifTrue:[
waitingProcesses := OrderedCollection with:current
] ifFalse:[
waitingProcesses add:current
].
current state == #active ifTrue:[
current state:#wait.
].
Processor suspend:current
].
].
count := count - 1.
OperatingSystem unblockInterrupts
!
signalOnce
"wakeup waiters - but only once"
count == 0 ifTrue:[
self signal
]
!
signal
"waking up waiters"
|p|
OperatingSystem blockInterrupts.
count := count + 1.
(waitingProcesses notNil and:[waitingProcesses notEmpty]) ifTrue:[
p := waitingProcesses removeFirst.
OperatingSystem unblockInterrupts.
p resume.
^ self
].
OperatingSystem unblockInterrupts
!
critical:aBlock
"evaluate aBlock as a critical region; the receiver must be
created using Semaphore-forMutualExclusion"
self wait.
^ aBlock valueNowOrOnUnwindDo:[self signal].
! !