SemaphoreSet.st
author Claus Gittinger <cg@exept.de>
Sat, 16 Dec 1995 02:23:39 +0100
changeset 770 402958905760
parent 769 84cc1b36f27e
child 775 7b6c00a4708a
permissions -rw-r--r--
protocol of waitWithTImeOut: changed

IdentitySet subclass:#SemaphoreSet
	instanceVariableNames:''
	classVariableNames:''
	poolDictionaries:''
	category:'Kernel-Processes'
!

!SemaphoreSet class methodsFor:'documentation'!

documentation
"
    SemaphoreSet allow waiting until one of several semaphores become available.
"
!

example2
"
    |sema1 sema2 semaSet proc|

    sema1 := Semaphore new.
    sema2 := Semaphore new.
    semaSet := SemaphoreSet with:sema1 with:sema2.

    proc := [
        [
            |ret name|

            ret := semaSet waitWithTimeout:5.
            ret == sema1 ifTrue:[
                name := 'sema1'
            ] ifFalse:[ 
                ret == sema2 ifTrue:[
                    name := 'sema2'
                ] ifFalse:[
                    name := ret printString
                ]
            ].
            Transcript showCr: name, ' raised'.
            ret isNil ifTrue:[
                proc terminate
            ]
        ] loop
    ] fork.

    (Delay forSeconds:3) wait.
    sema1 signal.
    (Delay forSeconds:3) wait.
    sema2 signal.
"
!

examples
"
    |sema1 sema2 semaSet proc|

    sema1 := Semaphore new.
    sema2 := Semaphore new.
    semaSet := SemaphoreSet with:sema1 with:sema2.

    proc := [
        [
            |ret name|

            ret := semaSet wait.
            ret == sema1 ifTrue:[
                name := 'sema1'
            ] ifFalse:[ 
                ret == sema2 ifTrue:[
                    name := 'sema2'
                ]
            ].
            Transcript showCr: name, ' raised'.
            ret == sema2 ifTrue:[
                proc terminate
            ]
        ] loop
    ] fork.

    (Delay forSeconds:3) wait.
    sema1 signal.
    (Delay forSeconds:3) wait.
    sema2 signal.
"
!

history
    "Created: 14.12.1995 / 12:23:21 / stefan"
! !

!SemaphoreSet methodsFor:'wait'!

wait
    |currentProcess gotSema wasBlocked registeredAllSemas|

    currentProcess := Processor activeProcess.
    registeredAllSemas := false.

    wasBlocked := OperatingSystem blockInterrupts.
    [
        gotSema := self detect:[:sema|
            sema checkAndRegisterProcess:currentProcess
        ] ifNone:[
            registeredAllSemas := true.
            currentProcess suspendWithState:#wait.
            nil
        ].
    ] doWhile:[gotSema isNil].

    "
      we finaly got at least one of our semaphores.
      Now unregister from any semaphore, we are registered on.
    "
    self detect:[:sema|
        (sema == gotSema) ifTrue:[
            registeredAllSemas not        
        ] ifFalse:[        
            sema unregisterProcess:currentProcess.
            false
        ]
    ] ifNone:[].

    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
    ^ gotSema

    "Modified: 15.12.1995 / 23:10:07 / stefan"
!

waitWithTimeout:seconds
    "wait for any of the the semaphore, but abort the wait after some time.
     Return the first triggered semaphore if any, nil if we return due to a timeout."

    |currentProcess gotSema wasBlocked now endTime unblock timeoutOccured registeredAllSemas|

    currentProcess := Processor activeProcess.
    timeoutOccured := false.
    registeredAllSemas := false.

    wasBlocked := OperatingSystem blockInterrupts.

    seconds notNil ifTrue:[
        "
         calculate the end-time
        "
        now := OperatingSystem getMillisecondTime.
        endTime := OperatingSystem millisecondTimeAdd:now and:(seconds * 1000).

        unblock := [timeoutOccured := true. Processor resume:currentProcess].
        Processor addTimedBlock:unblock for:currentProcess atMilliseconds:endTime.
    ].

    [
        gotSema := self detect:[:sema|
            sema checkAndRegisterProcess:currentProcess
        ] ifNone:[
            registeredAllSemas := true.
            currentProcess suspendWithState:#wait.
            nil
        ].
    ] doWhile:[gotSema isNil and:[timeoutOccured not]].

    (timeoutOccured not and:[unblock notNil]) ifTrue:[
        Processor removeTimedBlock:unblock.
    ].

    "
      we finaly got at least one of our semaphores.
      Now unregister from any semaphore, we are registered on.
    "
    self detect:[:sema|
        (sema == gotSema) ifTrue:[
            registeredAllSemas not        
        ] ifFalse:[        
            sema unregisterProcess:currentProcess.
            false
        ]
    ] ifNone:[].

    wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
    ^ gotSema

    "Modified: 15.12.1995 / 23:10:54 / stefan"
    "Modified: 16.12.1995 / 02:22:53 / cg"
! !

!SemaphoreSet class methodsFor:'documentation'!

version
"
$Header: /cvs/stx/stx/libbasic/SemaphoreSet.st,v 1.3 1995-12-16 01:23:30 cg Exp $
"
! !