--- a/JavaMonitor.st Fri Aug 11 11:34:41 2017 +0100
+++ b/JavaMonitor.st Fri May 05 17:52:31 2017 +0200
@@ -23,8 +23,8 @@
"{ NameSpace: Smalltalk }"
Object subclass:#JavaMonitor
- instanceVariableNames:'owningProcess processesEntered monitorSema count waitingSema
- processesWaiting waitEnabled ownerPrintString'
+ instanceVariableNames:'owningProcess monitorSema count waitingSema waitEnabled
+ ownerPrintString'
classVariableNames:'instVarAccess'
poolDictionaries:''
category:'Languages-Java-Support'
@@ -81,72 +81,29 @@
!JavaMonitor methodsFor:'accessing'!
-activeProcess
- ^ Processor activeProcess
-!
-
-copyProcessesEntered
- ^ processesEntered copy.
-
- "Created: / 20-11-2011 / 14:45:24 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-!
-
count
^ count
!
processesEntered
- "dont do anything to me, access needs to be sync'd"
- ^ processesEntered.
+ "Return a alist of processes that entered the monitor. For testing / debugging purposes only!!"
+
+ ^ owningProcess isNil
+ ifTrue:[ #() ]
+ ifFalse:[ (Array with: owningProcess) , monitorSema waitingProcesses ]
"Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified (format): / 03-06-2017 / 23:10:31 / Jan Vrany <jan.vrany@fit.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, let's lower our counter so we know how many times
- we have to release it"
-
- "/ the lock is probably not helping here to protect against problems with
- "/ increment/decrement:
- "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
- "/ if after, everything is ok;
- "/ if before, the decremented value will be zero, which is probably wrong.
-
- "/ without the critical region, we might also get possible inconsistencies:
- "/ if written before, the counter will drop to zero
- "/ if written in-between, the counter wil ahve the old value decremented;
- "/ if written afterwards, everything is ok.
-
- "/ so, the lock should be really elsewhere, making sure that noone will count
- "/ the monitor at-all and the monitor is reininialized without anyone depending on the
- "/ count at all.
- "/ but then, no critical section is needed in reinitCounter!!.
-
- instVarAccess critical: [ count := count - 1 ].
-
- "Created: / 22-11-2011 / 10:49:33 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-!
-
disableWait
JavaVM monitorTrace ifTrue:[
Logger log: ('Waiting is disabled on monitor for %1' bindWith: ownerPrintString) severity:Logger severityDEBUG facility:#JVM.
].
"/ critical region not needed here
- "/ instVarAccess critical: [ waitEnabled := false ].
+ "/ self instVarAccessCritical: [ waitEnabled := false ].
waitEnabled := false.
"Created: / 30-11-2011 / 20:34:40 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
@@ -155,125 +112,23 @@
enableWait
"/ critical region not needed here
- "/ instVarAccess critical: [waitEnabled := true].
+ "/ self instVarAccessCritical: [waitEnabled := true].
waitEnabled := true
"Created: / 30-11-2011 / 20:34:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
"Modified (format): / 11-10-2013 / 11:17:58 / Jan Vrany <jan.vrany@fit.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"
-
- "/ the lock is probably not helping here to protect against problems with
- "/ increment/decrement:
- "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
- "/ if after, everything is ok;
- "/ if before, the decremented value will be zero, which is probably wrong.
-
- "/ without the critical region, we might also get possible inconsistencies:
- "/ if written before, the counter will drop to zero
- "/ if written in-between, the counter wil ahve the old value decremented;
- "/ if written afterwards, everything is ok.
-
- "/ so, the lock should be really elsewhere, making sure that noone will count
- "/ the monitor at-all and the monitor is reininialized without anyone depending on the
- "/ count at all.
- "/ but then, no critical section is needed in reinitCounter!!.
-
- instVarAccess critical: [ count := count + 1 ].
-
- "Created: / 22-11-2011 / 10:49:07 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 27-08-2012 / 10:42:11 / Jan Vrany <jan.vrany@fit.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>"
-!
+instVarAccessCritical: aBlock
+ ^ instVarAccess critical: aBlock.
-reinitCounter
- "owning process is different from previous, lets start counting from beginning"
-
- "/ the lock is probably not helping here to protect against problems with
- "/ increment/decrement:
- "/ the write-access here will be either done before incrementing/decrementing or after.
- "/ if after, everything is ok;
- "/ if before, the decremented value will be zero, which is probably wrong.
-
- "/ without the critical region, we might also get possible inconsistencies:
- "/ if written before, the counter will drop to zero
- "/ if written in-between, the counter wil ahve the old value decremented;
- "/ if written afterwards, everything is ok.
-
- "/ so, the lock should be really elsewhere, making sure that noone will count
- "/ the monitor at-all and the monitor is reininialized without anyone depending on the
- "/ count at all.
- "/ but then, no critical section is needed!!.
-
- instVarAccess critical: [ count := 1 ].
-
- "Created: / 22-11-2011 / 10:51:09 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-!
-
-reinitCounter: newCount
- "/ the lock is probably not helping here to protect against problems with
- "/ increment/decrement:
- "/ the write-access here will be either done before incrementing/decrementing or after.
- "/ if after, everything is ok;
- "/ if before, the decremented value will be zero, which is probably wrong.
-
- "/ without the critical region, we might also get possible inconsistencies:
- "/ if written before, the counter will drop to zero
- "/ if written in-between, the counter wil ahve the old value decremented;
- "/ if written afterwards, everything is ok.
-
- "/ so, the lock should be really elsewhere, making sure that noone will count
- "/ the monitor at-all and the monitor is reininialized without anyone depending on the
- "/ count at all.
- "/ but then, no critical section is needed!!.
-
- 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>"
+ "Created: / 03-06-2017 / 22:09:24 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 03-06-2017 / 23:15:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
waitEnabled
"/ critical region not needed here
- "/ instVarAccess critical: [ ^ waitEnabled].
+ "/ self instVarAccessCritical: [ ^ waitEnabled].
^ waitEnabled.
"Created: / 30-11-2011 / 20:34:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
@@ -281,19 +136,6 @@
!JavaMonitor methodsFor:'initialization'!
-initialize
- "Q: is this ever called?"
-
- owningProcess := nil.
- processesEntered := OrderedCollection new.
- monitorSema := Semaphore new: 1.
- processesWaiting := Dictionary new.
- waitingSema := Semaphore new: 0.
- waitEnabled := true.
-
- "Created: / 20-11-2011 / 13:28:28 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
-!
-
initializeFor: owningObject
self initializeFor: owningObject thread: 0 nestedLockCount: 0.
@@ -305,9 +147,7 @@
"/ self assert: (owningObject isJavaObject or:[owningObject isJavaClass]).
- processesEntered := OrderedCollection new.
waitEnabled := true.
- processesWaiting := Dictionary new.
waitingSema := Semaphore new:0.
ownerPrintString := owningObject class name , '@' , owningObject identityHash printString.
@@ -322,7 +162,6 @@
owningProcess := ObjectMemory processesKnownInVM detect:[:p|p id == threadId] ifNone:[nil].
self assert: owningProcess notNil.
- processesEntered add: owningProcess.
cnt timesRepeat:[
"/ JavaVM enteredMonitorsOf: owningProcess add: owningObject.
"/ JavaVM acquiredMonitorsOf: owningProcess add: owningObject.
@@ -332,42 +171,60 @@
].
"Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 03-06-2017 / 23:10:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaMonitor methodsFor:'public'!
acquire
| thisProcess |
- thisProcess := self activeProcess.
+ thisProcess := Processor activeProcess.
(self isOwnedBy: thisProcess) ifTrue: [
- self increment.
+ "/ the lock is probably not helping here to protect against problems with
+ "/ increment/decrement:
+ "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
+ "/ if after, everything is ok;
+ "/ if before, the decremented value will be zero, which is probably wrong.
+
+ "/ without the critical region, we might also get possible inconsistencies:
+ "/ if written before, the counter will drop to zero
+ "/ if written in-between, the counter wil ahve the old value decremented;
+ "/ if written afterwards, everything is ok.
+
+ "/ so, the lock should be really elsewhere, making sure that noone will count
+ "/ the monitor at-all and the monitor is reininialized without anyone depending on the
+ "/ count at all.
+ "/ but then, no critical section is needed in reinitCounter!!.
+
+ self instVarAccessCritical: [ count := count + 1 ].
^ self
].
monitorSema wait.
- self owningProcess: thisProcess.
+ owningProcess := thisProcess.
count := 1.
"Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 27-08-2012 / 11:45:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 03-06-2017 / 22:36:04 / Jan Vrany <jan.vrany@fit.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>"
+ "Modified: / 03-06-2017 / 23:11:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
exit
| thisProcess |
- thisProcess := self activeProcess.
- (self isOwnedBy: thisProcess) ifTrue: [ self release. ].
- processesEntered remove: thisProcess ifAbsent: nil.
+
+ "JV@2017-06-03: Question: Is it legal (i.e., is the good reason to) call #exit
+ on a monitor by a process that does not own it? Shouldn't we rather throw an
+ error"
+ thisProcess := Processor activeProcess.
+ (self isOwnedBy: thisProcess) ifTrue: [ self release. ].
"Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 26-08-2012 / 19:54:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified (format): / 03-06-2017 / 23:13:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
notify
@@ -379,7 +236,7 @@
JavaVM monitorTrace ifTrue:[
Logger
log: ('%1: notifying %2 processes' bindWith: thisProcess printString
- with: processesWaiting size)
+ with: waitingSema waitingProcesses size)
severity: Logger severityDEBUG
facility: #JVM.
].
@@ -387,7 +244,7 @@
Processor yield.
"Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 02-03-2015 / 14:06:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 05-05-2017 / 17:27:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
notifyAll
@@ -399,7 +256,7 @@
JavaVM monitorTrace ifTrue:[
Logger
log: ('%1: notifying all %2 processes' bindWith: thisProcess printString
- with: processesWaiting size)
+ with: waitingSema waitingProcesses size)
severity: Logger severityDEBUG
facility: #JVM.
].
@@ -407,27 +264,37 @@
Processor yield.
"Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 02-03-2015 / 14:06:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 05-05-2017 / 17:28:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
release
self assert: (self isOwnedBy: owningProcess).
count == 1 ifTrue: [
- self clearOwningProcess.
+ self instVarAccessCritical: [ owningProcess := nil ].
count := 0.
monitorSema signal.
] ifFalse: [
- self decrement.
+ "/ the lock is probably not helping here to protect against problems with
+ "/ increment/decrement:
+ "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
+ "/ if after, everything is ok;
+ "/ if before, the decremented value will be zero, which is probably wrong.
+
+ "/ without the critical region, we might also get possible inconsistencies:
+ "/ if written before, the counter will drop to zero
+ "/ if written in-between, the counter wil ahve the old value decremented;
+ "/ if written afterwards, everything is ok.
+
+ "/ so, the lock should be really elsewhere, making sure that noone will count
+ "/ the monitor at-all and the monitor is reininialized without anyone depending on the
+ "/ count at all.
+ "/ but then, no critical section is needed in reinitCounter!!.
+
+ self instVarAccessCritical: [ count := count - 1 ].
]
"Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
- "Modified: / 11-10-2013 / 11:18:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-releaseAll
- count timesRepeat: [self release].
-
- "Created: / 22-11-2011 / 13:05:20 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
+ "Modified: / 03-06-2017 / 22:24:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
wait
@@ -464,9 +331,8 @@
severity: #debug
facility: #JVM.
].
- self processesWaitingAdd: thisProcess.
countBeforeWait := count.
- self releaseAll.
+ count timesRepeat: [self release].
"JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
waitingSema waitWithTimeoutMs: timeOut
@@ -481,23 +347,21 @@
self acquire.
count := countBeforeWait.
- 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: / 02-03-2015 / 14:06:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 03-06-2017 / 22:52:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!JavaMonitor methodsFor:'queries'!
isAcquired
- ^ instVarAccess critical: [ owningProcess notNil ].
+ ^ self instVarAccessCritical: [ owningProcess notNil ].
"Created: / 20-11-2011 / 13:22:26 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
!
isOwnedBy: aProcess
- ^ instVarAccess critical: [ owningProcess == aProcess ].
+ ^ self instVarAccessCritical: [ owningProcess == aProcess ].
"Created: / 20-11-2011 / 13:23:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
! !