SemaphoreSet.st
author Stefan Vogel <sv@exept.de>
Sat, 16 Dec 1995 02:16:25 +0100
changeset 769 84cc1b36f27e
parent 757 93d5f6b86e98
child 770 402958905760
permissions -rw-r--r--
Fix cleanup after process resume in SemaphoreSet.

'From Smalltalk/X, Version:2.10.8 on 15-dec-1995 at 23:16:48'                   !

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
    |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"
! !

!SemaphoreSet class methodsFor:'documentation'!

version
"
$Header: /cvs/stx/stx/libbasic/SemaphoreSet.st,v 1.2 1995-12-16 01:16:24 stefan Exp $
"
! !