RecursionLock.st
author Claus Gittinger <cg@exept.de>
Thu, 18 Apr 1996 18:19:04 +0200
changeset 1215 43e8e17fd9f5
parent 1186 cf4c57ecabb8
child 1216 d7cbc6eb8dd4
permissions -rw-r--r--
added #wouldBlock

"
 COPYRIGHT (c) 1995 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.
"


Object subclass:#RecursionLock
	instanceVariableNames:'process sema'
	classVariableNames:''
	poolDictionaries:''
	category:'Kernel-Processes'
!

!RecursionLock class methodsFor:'documentation'!

copyright
"
 COPYRIGHT (c) 1995 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.
"

!

documentation
"
    like a Semaphore for mutual exclusion, but avoids the deadlock
    if a critical region is reentered by the same process again.
    I.e. allows reentering the critical region if the current process 
    is the one which did the original locking.

    example:

        |lock|

        lock := RecursionLock new.
        lock critical:[
            Transcript showCr:'in lock ...'.
            lock critical:[
                Transcript showCr:'again ...'
            ]
        ]

    in contrast to (wrong example):

        |lock|

        lock := Semaphore forMutualExclusion.
        lock critical:[
            Transcript showCr:'in lock ...'.
            lock critical:[
                '*** never reached - deadlock because sema is already locked ***'.
                '    (press CTRL-c and abort in the debugger)'.
                Transcript showCr:'again ...'
            ]
        ]
"
! !

!RecursionLock class methodsFor:'instance creation'!

new
    ^ self basicNew initialize

! !

!RecursionLock methodsFor:'private initialization'!

initialize
    sema := Semaphore forMutualExclusion
! !

!RecursionLock methodsFor:'queries'!

wouldBlock
    "return true, if the receiver would block the activeProcess
     if a wait was performed. False otherwise."

    process == Processor activeProcess ifTrue:[^ false].
    ^ sema wouldBlock

    "Created: 18.4.1996 / 17:18:08 / cg"
! !

!RecursionLock methodsFor:'wait & signal'!

critical:aBlock
    "evaluate aBlock as a critical region, but do not block,
     if this lock is already held by the current process."

    |active|

    active := Processor activeProcess.
    process == active ifTrue:[
        aBlock value
    ] ifFalse:[
        sema critical:[
            [
                process := active.
                aBlock value
            ] valueNowOrOnUnwindDo:[
                process := nil.
            ]
        ]
    ].

    "Modified: 13.4.1996 / 00:19:31 / stefan"
! !

!RecursionLock class methodsFor:'documentation'!

version 
    ^ '$Header: /cvs/stx/stx/libbasic/RecursionLock.st,v 1.9 1996-04-18 16:19:04 cg Exp $'
! !