--- a/Semaphore.st Tue Sep 21 20:00:49 2004 +0200
+++ b/Semaphore.st Tue Sep 21 20:06:25 2004 +0200
@@ -318,45 +318,6 @@
^ super new setCount:n
! !
-!Semaphore methodsFor:'friend-class interface'!
-
-checkAndRegisterProcess:process
- "interface for SemaphoreSet.
- If the semaphore is available, decrement it and return true.
- Otherwise register our process to be wakened up once the semaphore is available
- and return false.
- ATTENTION: this must be invoked with OperatingSystem-interrupts-blocked.
- "
-
- count > 0 ifTrue:[
- count := count - 1.
- count == 0 ifTrue:[
- lastOwnerID := Processor activeProcessId.
- ].
- ^ true
- ].
- (waitingProcesses isNil or:[(waitingProcesses includesIdentical:process) not]) ifTrue:[
- self addWaitingProcess:process.
- ].
- ^ false
-
- "Modified: 14.12.1995 / 10:32:17 / stefan"
- "Modified: 10.1.1997 / 21:42:18 / cg"
-!
-
-unregisterProcess:aProcess
- "interface for SemaphoreSet.
- Unregister our process from the Semaphore.
- ATTENTION: this must be invoked with OperatingSystem-interrupts-blocked."
-
- waitingProcesses notNil ifTrue:[
- self removeWaitingProcess:aProcess
- ].
-
- "Created: 14.12.1995 / 10:31:50 / stefan"
- "Modified: 1.2.1997 / 12:11:22 / cg"
-! !
-
!Semaphore methodsFor:'printing & storing'!
displayString
@@ -454,6 +415,12 @@
!Semaphore methodsFor:'private-accessing'!
+clear
+ "clear the semaphores count"
+
+ count := 0
+!
+
initSignals
"set the count of the semaphore to zero.
provided for ST-80 compatibility."
@@ -508,6 +475,152 @@
^ waitingProcesses ? #()
"Created: 18.7.1996 / 20:53:33 / cg"
+! !
+
+!Semaphore methodsFor:'semaphoreSet interface'!
+
+checkAndAddWaitingProcess:process
+ "interface for SemaphoreSet.
+ If the semaphore is available, decrement it and return true.
+ Otherwise register our process to be wakened up once the semaphore is available
+ and return false.
+ ATTENTION: this must be invoked with OperatingSystem-interrupts-blocked.
+ "
+
+ count > 0 ifTrue:[
+ count := count - 1.
+ count == 0 ifTrue:[
+ lastOwnerID := Processor activeProcessId.
+ ].
+ ^ true
+ ].
+ (waitingProcesses notNil and:[(waitingProcesses includesIdentical:process)]) ifFalse:[
+ self addWaitingProcess:process.
+ ].
+ ^ false
+
+ "Modified: 14.12.1995 / 10:32:17 / stefan"
+ "Modified: 10.1.1997 / 21:42:18 / cg"
+! !
+
+!Semaphore methodsFor:'signaling'!
+
+signal
+ "waking up (the first) waiter.
+ Q: should this be the highest prio waiter ?"
+
+ |wasBlocked|
+
+ wasBlocked := OperatingSystem blockInterrupts.
+ [
+ |p|
+
+ count := count + 1.
+ waitingProcesses notNil ifTrue:[
+ p := self removeFirstWaitingProcess.
+ p notNil ifTrue:[
+ Processor resume:p.
+ ].
+ ].
+ ] ensure:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ]
+
+ "Modified: / 4.2.1998 / 21:01:07 / cg"
+!
+
+signalForAll
+ "signal the semaphore for all waiters.
+ This can be used for process synchronization, if multiple processes are
+ waiting for a common event."
+
+ |wasBlocked|
+
+ waitingProcesses size ~~ 0 ifTrue:[
+ wasBlocked := OperatingSystem blockInterrupts.
+ [
+ |processes|
+
+ "first, make them all runnable, but do not schedule
+ (in case one has higher prio and goes into a wait immediately again.)"
+
+ processes := waitingProcesses.
+ waitingProcesses := nil.
+ processes do:[:eachWaitingProcess|
+ count := count + 1.
+ Processor makeRunnable:eachWaitingProcess.
+ ].
+ ] ensure:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ].
+ "now, schedule the highest priority process"
+ Processor reschedule
+ ]
+
+ "Modified: / 5.2.1998 / 10:40:26 / cg"
+!
+
+signalIf
+ "signal the semaphore, but only if being waited upon.
+ This can be used for one-shot semaphores (i.e. not remembering
+ previous signals)"
+
+ |wasBlocked|
+
+ waitingProcesses notNil ifTrue:[
+ wasBlocked := OperatingSystem blockInterrupts.
+ [
+ waitingProcesses size ~~ 0 ifTrue:[
+ self signal
+ ].
+ ] ensure:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ]
+ ]
+
+ "Modified: 28.2.1996 / 21:23:57 / cg"
+!
+
+signalOnce
+ "wakeup waiters - but only once.
+ I.e. if the semaphore has already been signalled, this is ignored."
+
+ |wasBlocked|
+
+ count <= 0 ifTrue:[
+ wasBlocked := OperatingSystem blockInterrupts.
+ "/ check again - now interrupts are blocked.
+ [
+ |p|
+
+ count <= 0 ifTrue:[
+ count := count + 1.
+ count == 1 ifTrue:[
+ waitingProcesses notNil ifTrue:[
+ p := self removeFirstWaitingProcess.
+ p notNil ifTrue:[
+ Processor resume:p.
+ ].
+ ].
+ ].
+ ].
+ ] ensure:[
+ wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+ ]
+ ]
+
+ "Modified: 28.2.1996 / 21:24:08 / cg"
+! !
+
+!Semaphore methodsFor:'testing'!
+
+isEmpty
+ "ST80 compatibility - return true if there are no waiters"
+
+ ^ waitingProcesses size == 0
+
+ "Created: / 3.5.1996 / 18:06:27 / cg"
+ "Modified: / 18.6.1998 / 16:07:38 / cg"
!
wouldBlock
@@ -519,24 +632,7 @@
^ count <= 0
! !
-!Semaphore methodsFor:'testing'!
-
-isEmpty
- "ST80 compatibility - return true if there are no waiters"
-
- ^ waitingProcesses size == 0
-
- "Created: / 3.5.1996 / 18:06:27 / cg"
- "Modified: / 18.6.1998 / 16:07:38 / cg"
-! !
-
-!Semaphore methodsFor:'wait & signal'!
-
-clear
- "clear the semaphores count"
-
- count := 0
-!
+!Semaphore methodsFor:'waiting'!
critical:aBlock
"evaluate aBlock as a critical region; the receiver must be
@@ -618,117 +714,6 @@
"Modified: / 21.7.1998 / 17:45:26 / cg"
!
-signal
- "waking up (the first) waiter.
- Q: should this be the highest prio waiter ?"
-
- |wasBlocked|
-
- wasBlocked := OperatingSystem blockInterrupts.
- [
- |p|
-
- count := count + 1.
- waitingProcesses notNil ifTrue:[
- p := self removeFirstWaitingProcess.
- p notNil ifTrue:[
- Processor resume:p.
- ].
- ].
- ] ensure:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ]
-
- "Modified: / 4.2.1998 / 21:01:07 / cg"
-!
-
-signalForAll
- "signal the semaphore for all waiters.
- This can be used for process synchronization, if multiple processes are
- waiting for a common event."
-
- |wasBlocked|
-
- waitingProcesses size > 0 ifTrue:[
- wasBlocked := OperatingSystem blockInterrupts.
- [
- |nWaiting|
-
- "/ first, make them all runnable, but do not schedule
- "/ (in case one has higher prio and goes into a wait
- "/ immediately again.)
-
- [(nWaiting := waitingProcesses size) > 0] whileTrue:[
- |p|
-
- p := self removeFirstWaitingProcess.
- count := count + 1.
- Processor makeRunnable:p.
- ].
- ] ensure:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ].
- "/
- "/ now, reschedule
- "/
- Processor reschedule
- ]
-
- "Modified: / 5.2.1998 / 10:40:26 / cg"
-!
-
-signalIf
- "signal the semaphore, but only if being waited upon.
- This can be used for one-shot semaphores (i.e. not remembering
- previous signals)"
-
- |wasBlocked|
-
- (waitingProcesses size > 0) ifTrue:[
- wasBlocked := OperatingSystem blockInterrupts.
- [
- (waitingProcesses size > 0) ifTrue:[
- self signal
- ].
- ] ensure:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ]
- ]
-
- "Modified: 28.2.1996 / 21:23:57 / cg"
-!
-
-signalOnce
- "wakeup waiters - but only once.
- I.e. if the semaphore has already been signalled, this is ignored."
-
- |wasBlocked|
-
- count <= 0 ifTrue:[
- wasBlocked := OperatingSystem blockInterrupts.
- "/ check again - now interrupts are blocked.
- [
- |p|
-
- count <= 0 ifTrue:[
- count := count + 1.
- count == 1 ifTrue:[
- waitingProcesses notNil ifTrue:[
- p := self removeFirstWaitingProcess.
- p notNil ifTrue:[
- Processor resume:p.
- ].
- ].
- ].
- ].
- ] ensure:[
- wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- ]
- ]
-
- "Modified: 28.2.1996 / 21:24:08 / cg"
-!
-
wait
"wait for the semaphore"
@@ -745,7 +730,7 @@
Thus, the count is not always non-zero after returning from
suspend.
"
- [count <= 0] whileTrue:[
+ [
self addWaitingProcess:activeProcess.
"
for some more descriptive info in processMonitor ...
@@ -757,13 +742,8 @@
self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
-
- count <= 0 ifTrue:[
- "/ care for someone manually resuming me (i.e. semaphore still not avail)...
- "/ being multiple times on waitingProcesses
- self removeWaitingProcess:activeProcess.
- ]
- ].
+ self removeWaitingProcess:activeProcess.
+ ] doUntil:[count > 0].
].
count := count - 1.
@@ -807,11 +787,7 @@
self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
- count <= 0 ifTrue:[
- "/ care for someone manually resuming me (i.e. semaphore still not avail)...
- "/ being multiple times on waitingProcesses
- self removeWaitingProcess:activeProcess.
- ]
+ self removeWaitingProcess:activeProcess.
].
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
@@ -846,30 +822,27 @@
However, polling is not the intended use of semaphores, though.
If milliSeconds is nil, wait without timeout."
- |activeProcess timeoutOccured wasBlocked unblock now endTime|
+ |activeProcess timeoutOccured wasBlocked timeoutBlock now endTime|
wasBlocked := OperatingSystem blockInterrupts.
count <= 0 ifTrue:[
- "
- with zero-timeout, this is a poll
- "
- milliSeconds = 0 ifTrue:[
+ "with zero-timeout, this is a poll"
+ milliSeconds == 0 ifTrue:[
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
^ nil
].
activeProcess := Processor activeProcess.
+ timeoutOccured := false.
- "
- calculate the end-time
- "
milliSeconds notNil ifTrue:[
+ "Wait with timeout: calculate the end-time"
now := OperatingSystem getMillisecondTime.
endTime := OperatingSystem millisecondTimeAdd:now and:milliSeconds.
- unblock := [timeoutOccured := true. Processor resume:activeProcess].
- Processor addTimedBlock:unblock for:activeProcess atMilliseconds:endTime.
+ timeoutBlock := [timeoutOccured := true. timeoutBlock:= nil. Processor resume:activeProcess].
+ Processor addTimedBlock:timeoutBlock for:activeProcess atMilliseconds:endTime.
].
"
@@ -878,19 +851,21 @@
Thus, the count is not always non-zero after returning from
suspend.
"
- [count <= 0] whileTrue:[
+ [
self addWaitingProcess:activeProcess.
- timeoutOccured := false.
"
for some more descriptive info in processMonitor ...
... set the state to #wait (instead of #suspend)
"
[
+ "sleep until resumed..."
activeProcess suspendWithState:#wait.
] ifCurtailed:[
- Processor removeTimedBlock:unblock.
- unblock := nil.
+ timeoutBlock notNil ifTrue:[
+ Processor removeTimedBlock:timeoutBlock.
+ timeoutBlock := nil.
+ ].
self removeWaitingProcess:activeProcess.
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
].
@@ -898,17 +873,17 @@
self removeWaitingProcess:activeProcess.
timeoutOccured ifTrue:[
wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
- unblock := nil.
^ nil
].
- ].
+ ] doUntil:[count > 0].
- unblock notNil ifTrue:[
- Processor removeTimedBlock:unblock.
- unblock := nil.
+ timeoutBlock notNil ifTrue:[
+ Processor removeTimedBlock:timeoutBlock.
+ timeoutBlock := nil.
].
].
+ "if we come here, we have accquired the semaphore"
count := count - 1.
count == 0 ifTrue:[
lastOwnerID := Processor activeProcessId.
@@ -923,5 +898,5 @@
!Semaphore class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.71 2003-10-28 21:16:45 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.72 2004-09-21 18:06:07 stefan Exp $'
! !