Semaphore.st
changeset 16631 ba77908696d0
parent 16625 09b045c29e25
child 16903 b8fc32d0daf3
--- a/Semaphore.st	Wed Jun 25 10:56:11 2014 +0200
+++ b/Semaphore.st	Wed Jun 25 11:52:24 2014 +0200
@@ -813,37 +813,36 @@
     wasBlocked := OperatingSystem blockInterrupts.
 
     count <= 0 ifTrue:[
-	activeProcess := Processor activeProcess.
-	"
-	 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.
-	"
-	[
-	    self addWaitingProcess:activeProcess.
-	    "
-	     for some more descriptive info in processMonitor ...
-	     ... set the state to #wait (instead of #suspend)
-	    "
-	    [
-		activeProcess suspendWithState:#wait
-	    ] ifCurtailed:[
-		"interrupts are not blocked when entered through Processor>>#interruptActive"
-		OperatingSystem blockInterrupts.
-		self removeWaitingProcess:activeProcess.
-		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-	    ].
-	    self removeWaitingProcess:activeProcess.
+        activeProcess := Processor activeProcess.
+        "
+         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.
+        "
+        [
+            self addWaitingProcess:activeProcess.
+            "
+             for some more descriptive info in processMonitor ...
+             ... set the state to #wait (instead of #suspend)
+            "
+            [
+                activeProcess suspendWithState:#wait
+            ] ifCurtailed:[
+                "interrupts are not blocked when entered through Processor>>#interruptActive"
+                OperatingSystem blockInterrupts.
+                self removeWaitingProcess:activeProcess.
+                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+            ].
+            self removeWaitingProcess:activeProcess.
 
-	    count <= 0
-	] whileTrue.
+            count <= 0
+        ] whileTrue.
     ].
 
     count := count - 1.
     count == 0 ifTrue:[
-	activeProcess isNil ifTrue:[activeProcess := Processor activeProcess].
-	lastOwnerId := activeProcess id.
+        lastOwnerId := Processor activeProcessId.
     ].
     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
 
@@ -923,90 +922,178 @@
     wasBlocked := OperatingSystem blockInterrupts.
 
     count <= 0 ifTrue:[
-	"with zero-timeout, this is a poll"
-	milliSeconds == 0 ifTrue:[
-	    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-	    ^ nil
-	].
+        "with zero-timeout, this is a poll"
+        milliSeconds == 0 ifTrue:[
+            wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+            ^ nil
+        ].
 
-	activeProcess := Processor activeProcess.
-	timeoutOccured := false.
+        activeProcess := Processor activeProcess.
+        timeoutOccured := false.
 
-	milliSeconds notNil ifTrue:[
-	    "Wait with timeout: calculate the end-time"
-	    now := OperatingSystem getMillisecondTime.
-	    endTime := OperatingSystem millisecondTimeAdd:now and:milliSeconds.
+        milliSeconds notNil ifTrue:[
+            "Wait with timeout: calculate the end-time"
+            now := OperatingSystem getMillisecondTime.
+            endTime := OperatingSystem millisecondTimeAdd:now and:milliSeconds.
 
-	    timeoutBlock := [
-		    timeoutOccured := true.
-		    timeoutBlock:= nil.
-		    Processor resume:activeProcess.
-		].
-	    Processor addTimedBlock:timeoutBlock for:activeProcess atMilliseconds:endTime.
-	].
+            timeoutBlock := [
+                    timeoutOccured := true.
+                    timeoutBlock:= nil.
+                    Processor resume:activeProcess.
+                ].
+            Processor addTimedBlock:timeoutBlock for:activeProcess atMilliseconds:endTime.
+        ].
 
-	"
-	 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.
-	"
-	[
-	    self addWaitingProcess:activeProcess.
+        "
+         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.
+        "
+        [
+            self addWaitingProcess:activeProcess.
 
-	    "
-	     for some more descriptive info in processMonitor ...
-	     ... set the state to #wait (instead of #suspend)
-	    "
-	    [
-		"sleep until resumed..."
-		activeProcess suspendWithState:#wait.
-	    ] ifCurtailed:[
-		"interrupts are not blocked when entered through Processor>>#interruptActive"
-		OperatingSystem blockInterrupts.
-		timeoutBlock notNil ifTrue:[
-		    Processor removeTimedBlock:timeoutBlock.
-		    timeoutBlock := nil.
-		].
-		self removeWaitingProcess:activeProcess.
-		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-	    ].
+            "
+             for some more descriptive info in processMonitor ...
+             ... set the state to #wait (instead of #suspend)
+            "
+            [
+                "sleep until resumed..."
+                activeProcess suspendWithState:#wait.
+            ] ifCurtailed:[
+                "interrupts are not blocked when entered through Processor>>#interruptActive"
+                OperatingSystem blockInterrupts.
+                timeoutBlock notNil ifTrue:[
+                    Processor removeTimedBlock:timeoutBlock.
+                    timeoutBlock := nil.
+                ].
+                self removeWaitingProcess:activeProcess.
+                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+            ].
 
-	    self removeWaitingProcess:activeProcess.
-	    timeoutOccured ifTrue:[
-		wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
-		^ nil
-	    ].
+            self removeWaitingProcess:activeProcess.
+            timeoutOccured ifTrue:[
+                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+                ^ nil
+            ].
 
-	    count <= 0
-	] whileTrue.
+            count <= 0
+        ] whileTrue.
 
-	timeoutBlock notNil ifTrue:[
-	    Processor removeTimedBlock:timeoutBlock.
-	    timeoutBlock := nil.
-	].
+        timeoutBlock notNil ifTrue:[
+            Processor removeTimedBlock:timeoutBlock.
+            timeoutBlock := nil.
+        ].
     ].
 
     "if we come here, we have acquired the semaphore"
     count := count - 1.
     count == 0 ifTrue:[
-	activeProcess isNil ifTrue:[activeProcess := Processor activeProcess].
-	lastOwnerId := activeProcess id.
+        lastOwnerId := Processor activeProcessId.
     ].
     wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
     ^ self
 
     "Modified: / 13-12-1995 / 13:27:24 / stefan"
     "Modified: / 11-08-2011 / 14:37:00 / cg"
+!
+
+waitWithTimeoutMs:milliSeconds state:waitStateSymbol
+    "wait for the semaphore, but abort the wait after some time.
+     return the receiver if the semaphore triggered normal, nil if we return
+     due to a timeout.
+     With zero timeout, this can be used to poll a semaphore (returning
+     the receiver if the semaphore is available, nil if not).
+     However, polling is not the intended use of semaphores, though.
+     If milliSeconds is nil, wait without timeout.
+
+     waitStateSymbol is the state the process is set to while waiting - normally #wait."
+
+    |activeProcess timeoutOccured wasBlocked timeoutBlock now endTime|
+
+    wasBlocked := OperatingSystem blockInterrupts.
+
+    count <= 0 ifTrue:[
+        "with zero-timeout, this is a poll"
+        milliSeconds == 0 ifTrue:[
+            wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+            ^ nil
+        ].
+
+        activeProcess := Processor activeProcess.
+        timeoutOccured := false.
+
+        milliSeconds notNil ifTrue:[
+            "Wait with timeout: calculate the end-time"
+            now := OperatingSystem getMillisecondTime.
+            endTime := OperatingSystem millisecondTimeAdd:now and:milliSeconds.
+
+            timeoutBlock := [
+                    timeoutOccured := true.
+                    timeoutBlock:= nil.
+                    Processor resume:activeProcess.
+                ].
+            Processor addTimedBlock:timeoutBlock for:activeProcess atMilliseconds:endTime.
+        ].
+
+        "
+         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.
+        "
+        [
+            self addWaitingProcess:activeProcess.
+
+            "
+             for some more descriptive info in processMonitor ...
+             ... set the state to #wait (instead of #suspend)
+            "
+            [
+                "sleep until resumed..."
+                activeProcess suspendWithState:waitStateSymbol.
+            ] ifCurtailed:[
+                "interrupts are not blocked when entered through Processor>>#interruptActive"
+                OperatingSystem blockInterrupts.
+                timeoutBlock notNil ifTrue:[
+                    Processor removeTimedBlock:timeoutBlock.
+                    timeoutBlock := nil.
+                ].
+                self removeWaitingProcess:activeProcess.
+                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+            ].
+
+            self removeWaitingProcess:activeProcess.
+            timeoutOccured ifTrue:[
+                wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+                ^ nil
+            ].
+
+            count <= 0
+        ] whileTrue.
+
+        timeoutBlock notNil ifTrue:[
+            Processor removeTimedBlock:timeoutBlock.
+            timeoutBlock := nil.
+        ].
+    ].
+
+    "if we come here, we have acquired the semaphore"
+    count := count - 1.
+    count == 0 ifTrue:[
+        lastOwnerId := Processor activeProcessId.
+    ].
+    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
+    ^ self
 ! !
 
 !Semaphore class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.97 2014-06-24 17:10:33 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.98 2014-06-25 09:52:24 stefan Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.97 2014-06-24 17:10:33 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Semaphore.st,v 1.98 2014-06-25 09:52:24 stefan Exp $'
 ! !