"
COPYRIGHT (c) 1996-2011 by Claus Gittinger
New code and modifications done at SWING Research Group [1]:
COPYRIGHT (c) 2010-2011 by Jan Vrany, Jan Kurs and Marcel Hlopko
SWING Research Group, Czech Technical University in Prague
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.
[1] Code written at SWING Research Group contains a signature
of one of the above copright owners. For exact set of such code,
see the differences between this version and version stx:libjava
as of 1.9.2010
"
"{ Package: 'stx:libjava' }"
Object subclass:#JavaMonitor
instanceVariableNames:'owningProcess processesEntered monitorSema count waitingSema
processesWaiting waitEnabled ownerPrintString'
classVariableNames:'instVarAccess'
poolDictionaries:''
category:'Languages-Java-Support'
!
!JavaMonitor class methodsFor:'documentation'!
copyright
"
COPYRIGHT (c) 1996-2011 by Claus Gittinger
New code and modifications done at SWING Research Group [1]:
COPYRIGHT (c) 2010-2011 by Jan Vrany, Jan Kurs and Marcel Hlopko
SWING Research Group, Czech Technical University in Prague
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.
[1] Code written at SWING Research Group contains a signature
of one of the above copright owners. For exact set of such code,
see the differences between this version and version stx:libjava
as of 1.9.2010
"
! !
!JavaMonitor class methodsFor:'initialization'!
initialize
instVarAccess := RecursionLock forMutualExclusion.
"Created: / 29-11-2011 / 11:23:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !
!JavaMonitor class methodsFor:'instance creation'!
for: owningObject
^ self basicNew initializeFor: owningObject.
"Created: / 30-11-2011 / 20:39:55 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !
!JavaMonitor methodsFor:'accessing'!
activeProcess
^ Processor activeProcess
!
copyProcessesEntered
^ processesEntered copy.
"Created: / 20-11-2011 / 14:45:24 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
processesEntered
"dont do anything to me, access needs to be sync'd"
^ processesEntered.
"Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !
!JavaMonitor methodsFor:'atomic'!
addProcess: aProcess
instVarAccess critical: [ processesEntered add: aProcess ].
"Created: / 20-11-2011 / 20:30:07 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
clearOwningProcess
instVarAccess critical: [ owningProcess := nil ].
"Created: / 20-11-2011 / 20:34:27 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
decrement
"owning process released monitor, lets lower our counter so we know how many times
do we have to release it"
instVarAccess critical: [ count := count - 1 ].
"Created: / 22-11-2011 / 10:49:33 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
disableWait
Logger log: ('Waiting is disabled on monitor for %1' bindWith: ownerPrintString) severity:#debug facility:#JVM.
instVarAccess critical: [ waitEnabled := false ].
"Created: / 30-11-2011 / 20:34:40 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
"Modified: / 10-05-2012 / 00:24:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
enableWait
instVarAccess critical: [waitEnabled := true].
"Created: / 30-11-2011 / 20:34:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
increment
"owning process entered monitor again (recursion ...), lets raise our counter so we know how many times
do we have to release it"
instVarAccess critical: [ count := count + 1 ].
"Created: / 22-11-2011 / 10:49:07 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
owningProcess: aProcess
instVarAccess critical: [ owningProcess := aProcess ].
"Created: / 20-11-2011 / 20:32:26 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
processesWaitingAdd: aProcess
instVarAccess
critical: [
self assert: (processesWaiting includesKey: aProcess) not.
processesWaiting at: aProcess put: count
].
"Created: / 22-11-2011 / 11:57:50 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
processesWaitingRestore: aProcess
instVarAccess
critical: [
self assert: (processesWaiting includesKey: aProcess).
self reinitCounter: (processesWaiting at: aProcess).
processesWaiting removeKey: aProcess
].
"Created: / 22-11-2011 / 12:59:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
reinitCounter
"owning process is different from previous, lets start counting from beginning"
instVarAccess critical: [ count := 1 ].
"Created: / 22-11-2011 / 10:51:09 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
reinitCounter: newCount
instVarAccess critical: [ count := newCount ].
"Created: / 22-11-2011 / 13:00:51 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
removeProcess: aProcess
instVarAccess
critical: [
self assert: processesEntered last == aProcess.
processesEntered remove: aProcess
].
"Created: / 20-11-2011 / 20:28:37 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
waitEnabled
instVarAccess critical: [ ^ waitEnabled].
"Created: / 30-11-2011 / 20:34:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !
!JavaMonitor methodsFor:'initialization'!
initialize
owningProcess := nil.
processesEntered := OrderedCollection new.
monitorSema := Semaphore new: 1.
processesWaiting := Dictionary new.
waitingSema := Semaphore new: 0.
waitEnabled.
"Created: / 20-11-2011 / 13:28:28 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
initializeFor: owningObject
owningProcess := nil.
processesEntered := OrderedCollection new.
monitorSema := Semaphore new: 1.
processesWaiting := Dictionary new.
waitingSema := Semaphore new: 0.
waitEnabled := true.
ownerPrintString := owningObject class name , '@' , owningObject identityHash printString.
"Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
"Modified: / 10-05-2012 / 10:12:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaMonitor methodsFor:'public'!
acquire
| thisProcess |
thisProcess := self activeProcess.
(self isOwnedBy: thisProcess) ifTrue: [
self increment.
^ self
].
monitorSema wait.
self owningProcess: thisProcess.
self reinitCounter.
"Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
enter
| thisProcess |
thisProcess := self activeProcess.
self addProcess: thisProcess.
self acquire.
"Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
exit
| thisProcess |
thisProcess := self activeProcess.
(self isOwnedBy: thisProcess) ifTrue: [ self release. ].
processesEntered remove: thisProcess ifAbsent: nil.
"Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
notify
"wakeup one waiting process"
| thisProcess |
thisProcess := Processor activeProcess.
self assert: (self isOwnedBy: thisProcess).
Logger
log: ('%1: notifying %2 processes' bindWith: thisProcess printString
with: processesWaiting size)
severity: #debug
facility: #JVM.
waitingSema signal.
Processor yield.
"Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
notifyAll
"wakeup one waiting process"
| thisProcess |
thisProcess := Processor activeProcess.
self assert: (self isOwnedBy: thisProcess).
Logger
log: ('%1: notifying all %2 processes' bindWith: thisProcess printString
with: processesWaiting size)
severity: #debug
facility: #JVM.
waitingSema signalForAll.
Processor yield.
"Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
release
| thisProcess |
thisProcess := self activeProcess.
self assert: (self isOwnedBy: owningProcess).
count == 1 ifTrue: [
self clearOwningProcess.
monitorSema signal.
] ifFalse: [
self decrement.
]
"Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
releaseAll
count timesRepeat: [self release].
"Created: / 22-11-2011 / 13:05:20 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
wait
"make owning process to go to wait"
self waitForMilliseconds: nil.
"Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
waitForMilliseconds: timeOut
"make owning process to go to wait, but not longer than timeout"
| thisProcess |
thisProcess := Processor activeProcess.
self assert: (self isOwnedBy: thisProcess).
self waitEnabled ifFalse: [
Logger
log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead'
bindWith: thisProcess printString
with: ownerPrintString)
severity: #debug
facility: #JVM.
^ self.
].
Logger
log: ('%1 is going to wait on %3 for timeout: %2'
bindWith: thisProcess printString
with: timeOut
with: ownerPrintString printString)
severity: #debug
facility: #JVM.
self processesWaitingAdd: thisProcess.
self releaseAll.
"JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
waitingSema waitWithTimeoutMs: timeOut
].
Logger
log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3'
bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString)
severity: #debug
facility: #JVM.
self acquire.
self processesWaitingRestore: thisProcess.
"Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
"Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
"Modified: / 10-05-2012 / 00:24:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaMonitor methodsFor:'queries'!
isAcquired
^ instVarAccess critical: [ owningProcess notNil ].
"Created: / 20-11-2011 / 13:22:26 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
isOwnedBy: aProcess
^ instVarAccess critical: [ owningProcess == aProcess ].
"Created: / 20-11-2011 / 13:23:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !
!JavaMonitor class methodsFor:'documentation'!
version_SVN
^ '$Id$'
! !
JavaMonitor initialize!