Semaphore.st
author claus
Fri, 05 Aug 1994 02:55:07 +0200
changeset 92 0c73b48551ac
parent 88 81dacba7a63a
child 93 e31220cb391f
permissions -rw-r--r--
*** empty log message ***

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