JavaMonitor.st
changeset 3783 f7c384698e7f
parent 3780 57bbc3e4d650
child 3784 b0c56287a058
equal deleted inserted replaced
3782:32e335ed7c6f 3783:f7c384698e7f
    21 "{ Package: 'stx:libjava' }"
    21 "{ Package: 'stx:libjava' }"
    22 
    22 
    23 "{ NameSpace: Smalltalk }"
    23 "{ NameSpace: Smalltalk }"
    24 
    24 
    25 Object subclass:#JavaMonitor
    25 Object subclass:#JavaMonitor
    26 	instanceVariableNames:'owningProcess monitorSema count waitingSema waitEnabled
    26 	instanceVariableNames:'process sema count waitingSema waitEnabled ownerPrintString'
    27 		ownerPrintString'
       
    28 	classVariableNames:''
    27 	classVariableNames:''
    29 	poolDictionaries:''
    28 	poolDictionaries:''
    30 	category:'Languages-Java-Support'
    29 	category:'Languages-Java-Support'
    31 !
    30 !
    32 
    31 
    78 
    77 
    79 owningProcess
    78 owningProcess
    80     "Return the process that has acquired (entered) the receiver or
    79     "Return the process that has acquired (entered) the receiver or
    81      nil if no process currently has the monitor."
    80      nil if no process currently has the monitor."
    82 
    81 
    83     ^ owningProcess
    82     ^ process
    84 
    83 
    85     "Created: / 12-08-2017 / 23:11:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    84     "Created: / 12-08-2017 / 23:11:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    86 !
    85 !
    87 
    86 
    88 processesEntered
    87 processesEntered
    89     "Return a alist of processes that entered the monitor. For testing / debugging purposes only!!"
    88     "Return a alist of processes that entered the monitor. For testing / debugging purposes only!!"
    90 
    89 
    91     ^ owningProcess isNil 
    90     ^ process isNil
    92         ifTrue:[ #() ]
    91         ifTrue:[ #() ]
    93         ifFalse:[ (Array with: owningProcess) , monitorSema waitingProcesses ]
    92         ifFalse:[ (Array with: process) , sema waitingProcesses ]
    94 
    93 
    95     "Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
    94     "Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
    96     "Modified (format): / 03-06-2017 / 23:10:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    95     "Modified (format): / 03-06-2017 / 23:10:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    97 ! !
    96 ! !
    98 
    97 
   112 
   111 
   113 enableWait
   112 enableWait
   114     "/ critical region not needed here
   113     "/ critical region not needed here
   115     "/ self instVarAccessCritical: [waitEnabled := true].
   114     "/ self instVarAccessCritical: [waitEnabled := true].
   116     waitEnabled := true
   115     waitEnabled := true
   117     
   116 
   118     "Created: / 30-11-2011 / 20:34:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   117     "Created: / 30-11-2011 / 20:34:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   119     "Modified (format): / 11-10-2013 / 11:17:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   118     "Modified (format): / 11-10-2013 / 11:17:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   120 !
   119 !
   121 
   120 
   122 waitEnabled
   121 waitEnabled
   134 
   133 
   135     "Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   134     "Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   136     "Modified: / 26-08-2012 / 17:25:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   135     "Modified: / 26-08-2012 / 17:25:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   137 !
   136 !
   138 
   137 
   139 initializeFor:owningObject thread:threadId nestedLockCount:cnt 
   138 initializeFor:owningObject thread:threadId nestedLockCount:cnt
   140 
   139 
   141 "/    self assert: (owningObject isJavaObject or:[owningObject isJavaClass]).
   140 "/    self assert: (owningObject isJavaObject or:[owningObject isJavaClass]).
   142 
   141 
   143     waitEnabled := true.
   142     waitEnabled := true.
   144     waitingSema := Semaphore new:0.
   143     waitingSema := Semaphore new:0.
   145     ownerPrintString := owningObject class name , '@' , owningObject identityHash printString.
   144     ownerPrintString := owningObject class name , '@' , owningObject identityHash printString.
   146 
   145 
   147     "/Not locked...    
   146     "/Not locked...
   148     threadId == 0 ifTrue:[
   147     threadId == 0 ifTrue:[
   149         monitorSema := Semaphore new:1.
   148         sema := Semaphore new:1.
   150         count := 0.
   149         count := 0.
   151         ^self.
   150         ^self.
   152     ] ifFalse: [
   151     ] ifFalse: [
   153         "threadId is not zero (zero is threadId of scheduler process, which will never try to acquire the monitor)"
   152         "threadId is not zero (zero is threadId of scheduler process, which will never try to acquire the monitor)"
   154         "so it means it is possible that the thin lock is already locked for other thread, we must be careful " 
   153         "so it means it is possible that the thin lock is already locked for other thread, we must be careful "
   155 
   154 
   156         owningProcess := ObjectMemory processesKnownInVM detect:[:p|p id == threadId] ifNone:[nil].
   155         process := ObjectMemory processesKnownInVM detect:[:p|p id == threadId] ifNone:[nil].
   157         self assert: owningProcess notNil.
   156         self assert: process notNil.
   158         cnt timesRepeat:[
   157         cnt timesRepeat:[
   159 "/            JavaVM enteredMonitorsOf:  owningProcess add: owningObject.
   158 "/            JavaVM enteredMonitorsOf:  owningProcess add: owningObject.
   160 "/            JavaVM acquiredMonitorsOf: owningProcess add: owningObject.
   159 "/            JavaVM acquiredMonitorsOf: owningProcess add: owningObject.
   161         ].
   160         ].
   162         monitorSema := Semaphore new: 0.
   161         sema := Semaphore new: 0.
   163         count := cnt.
   162         count := cnt.
   164     ].
   163     ].
   165 
   164 
   166     "Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   165     "Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   167     "Modified: / 03-06-2017 / 23:10:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   166     "Modified: / 03-06-2017 / 23:10:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   172 acquire
   171 acquire
   173     "Acquire (enter) the monitor and return `true`.
   172     "Acquire (enter) the monitor and return `true`.
   174 
   173 
   175      See JVM spec, section 4.5, MONITORENTER.
   174      See JVM spec, section 4.5, MONITORENTER.
   176     "
   175     "
   177     | thisProcess wasBlocked hasAcquired |
   176     | active wasBlocked acquired |
   178     hasAcquired := nil.
   177     acquired := nil.
   179     thisProcess := Processor activeProcess.
   178     active := Processor activeProcess.
   180     owningProcess == thisProcess ifTrue:[ 
   179     process == active ifTrue:[
   181         "/ Process already ackquired the monitor, increase the
   180         "/ Process already ackquired the monitor, increase the
   182         "/ count and continue...
   181         "/ count and continue...
   183         count := count + 1.
   182         count := count + 1.
   184         ^self.
   183         ^true.
   185     ].
   184     ].
   186     wasBlocked := OperatingSystem blockInterrupts.
   185     wasBlocked := OperatingSystem blockInterrupts.
   187     [ 
   186     [
   188         (owningProcess notNil and:[ owningProcess isDead ]) ifTrue:[ 
   187         (process notNil and:[ process isDead ]) ifTrue:[
   189             "/ Process that acquired the monitor died without releasing it.
   188             "/ Process that acquired the monitor died without releasing it.
   190             "/ This should not happen.
   189             "/ This should not happen.
   191             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].    
   190             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   192             self assert: false description: 'Process that acquired the monitor died without releasing it'.
   191             self assert: false description: 'Process that acquired the monitor died without releasing it'.
   193             owningProcess := nil.
   192             process := nil.
   194             count := 0.
   193             count := 0.
   195         ].
   194         ].
   196         "/ We need to know that we already waited on and got semaphore
   195         "/ We need to know that we already waited on and got semaphore
   197         "/ in case the Semaphore >> #wait is prematurely terminated.
   196         "/ in case the Semaphore >> #wait is prematurely terminated.
   198         "/ Q: Can this actually happen? If so, how?
   197         "/ Q: Can this actually happen? If so, how?
   199         hasAcquired := monitorSema wait. 
   198         acquired := sema wait.
   200         owningProcess := thisProcess.
   199         process := active.
   201         count := 1.
   200         count := 1.
   202         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   201         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   203     ] ifCurtailed:[
   202     ] ifCurtailed:[
   204         hasAcquired notNil ifTrue:[
   203         acquired notNil ifTrue:[
   205             OperatingSystem blockInterrupts.
   204             OperatingSystem blockInterrupts.
   206             count := 0.
   205             count := 0.
   207             owningProcess := nil.
   206             process := nil.
   208             monitorSema signal.
   207             sema signal.
   209         ].
   208         ].
   210         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].       
   209         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
   211     ]
   210     ].
       
   211     ^true.
   212 
   212 
   213     "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   213     "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   214     "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   214     "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   215     "Modified (comment): / 14-08-2017 / 09:34:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   215     "Modified (comment): / 14-08-2017 / 09:34:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   216 !
   216 !
   217 
   217 
   218 enter
   218 enter
   219     <resource: #obsolete>
   219     <resource: #obsolete>
   220     self obsoleteMethodWarning: 'Use #acquire instead'.     
   220     self obsoleteMethodWarning: 'Use #acquire instead'.
   221     ^ self acquire.
   221     ^ self acquire.
   222 
   222 
   223     "Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   223     "Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   224     "Modified: / 14-08-2017 / 10:20:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   224     "Modified: / 14-08-2017 / 10:20:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   225 !
   225 !
   226 
   226 
   227 exit
   227 exit
   228     <resource: #obsolete>
   228     <resource: #obsolete>
   229     self obsoleteMethodWarning: 'Use #release instead'.     
   229     self obsoleteMethodWarning: 'Use #release instead'.
   230     ^ self release.
   230     ^ self release.
   231 
   231 
   232     "Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   232     "Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   233     "Modified: / 14-08-2017 / 10:20:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   233     "Modified: / 14-08-2017 / 10:20:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   234 !
   234 !
   244 
   244 
   245 notify: all
   245 notify: all
   246     "
   246     "
   247     An implementation of java.lang.Object#notify() and #notifyAll(). If `all` is
   247     An implementation of java.lang.Object#notify() and #notifyAll(). If `all` is
   248     `true` then all waiting threads are notified (see #norifyAll()) otherwise only
   248     `true` then all waiting threads are notified (see #norifyAll()) otherwise only
   249     one thread is notified (see #notify()). Returns `true` after when threads have 
   249     one thread is notified (see #notify()). Returns `true` after when threads have
   250     been notified or `false` if calling thread does not own the monitor.
   250     been notified or `false` if calling thread does not own the monitor.
   251 
   251 
   252     See Java API documentation for java.lang.Object#notify() and #notifyAll().
   252     See Java API documentation for java.lang.Object#notify() and #notifyAll().
   253         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify()
   253         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify()
   254         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notifyAll()
   254         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notifyAll()
   255     "
   255     "
   256     
   256 
   257     | thisProcess |
   257     | active |
   258     thisProcess := Processor activeProcess.
   258     active := Processor activeProcess.
   259     owningProcess == thisProcess ifFalse:[ 
   259     process == active ifFalse:[
   260         "/ Oops,  calling thread does not own the monitor. return false
   260         "/ Oops,  calling thread does not own the monitor. return false
   261         "/ immediately. The caller is responsible for throwing
   261         "/ immediately. The caller is responsible for throwing
   262         "/ IllegalMonitorStateException...
   262         "/ IllegalMonitorStateException...
   263         ^ false.
   263         ^ false.
   264     ].
   264     ].
   265     JavaVM monitorTrace ifTrue:[
   265     JavaVM monitorTrace ifTrue:[
   266         Logger 
   266         Logger
   267             log: ('%1: notifying %1%2 processes' bindWith: thisProcess printString
   267             log: ('%1: notifying %1%2 processes' bindWith: active printString
   268                     with: (all ifTrue:[ 'all ' ] ifFalse:[ '' ])
   268                     with: (all ifTrue:[ 'all ' ] ifFalse:[ '' ])
   269                     with: waitingSema waitingProcesses size)
   269                     with: waitingSema waitingProcesses size)
   270             severity: Logger severityDEBUG
   270             severity: Logger severityDEBUG
   271             facility: #JVM.
   271             facility: #JVM.
   272     ].
   272     ].
   289 release
   289 release
   290     "Release (leave) the monitor and return `true` if
   290     "Release (leave) the monitor and return `true` if
   291      monitor was release, `false` if monitor has not
   291      monitor was release, `false` if monitor has not
   292      been released (because calling thread does not own it).
   292      been released (because calling thread does not own it).
   293 
   293 
   294      See JVM spec, section 4.5, MONITOREXIT.       
   294      See JVM spec, section 4.5, MONITOREXIT.
   295     "
   295     "
   296     | thisProcess wasBlocked |
   296     | active wasBlocked |
   297 
   297 
   298     thisProcess := Processor activeProcess.
   298     active := Processor activeProcess.
   299     owningProcess == thisProcess ifFalse:[ 
   299     process == active ifFalse:[
   300         "/ Oops,  calling thread does not own the monitor. return false
   300         "/ Oops,  calling thread does not own the monitor. return false
   301         "/ immediately. The caller is responsible for throwing
   301         "/ immediately. The caller is responsible for throwing
   302         "/ IllegalMonitorStateException...
   302         "/ IllegalMonitorStateException...
   303         ^ false.
   303         ^ false.
   304     ].
   304     ].
   305     wasBlocked := OperatingSystem blockInterrupts.
   305     wasBlocked := OperatingSystem blockInterrupts.
   306     count == 1 ifTrue:[ 
   306     count == 1 ifTrue:[
   307         owningProcess := nil.
   307         process := nil.
   308         count := 0.
   308         count := 0.
   309         monitorSema signal.
   309         sema signal.
   310     ] ifFalse:[ 
   310     ] ifFalse:[
   311         count := count - 1.
   311         count := count - 1.
   312     ].
   312     ].
   313     wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
   313     wasBlocked ifFalse:[ OperatingSystem unblockInterrupts ].
   314     ^ true
   314     ^ true
   315 
   315 
   317     "Modified: / 12-08-2017 / 21:28:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   317     "Modified: / 12-08-2017 / 21:28:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   318     "Modified (comment): / 14-08-2017 / 09:35:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   318     "Modified (comment): / 14-08-2017 / 09:35:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   319 !
   319 !
   320 
   320 
   321 wait
   321 wait
   322     <resource: #obsolete>    
   322     <resource: #obsolete>
   323     self obsoleteFeatureWarning: 'Use `waitForMilliseconds: nil` insteead'.        
   323     self obsoleteFeatureWarning: 'Use `waitForMilliseconds: nil` insteead'.
   324     ^ self waitForMilliseconds: nil.
   324     ^ self waitForMilliseconds: nil.
   325 
   325 
   326     "Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   326     "Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   327     "Modified: / 14-08-2017 / 09:37:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   327     "Modified: / 14-08-2017 / 09:37:18 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   328 !
   328 !
   329 
   329 
   330 waitForMilliseconds: timeOut 
   330 waitForMilliseconds: timeOut
   331     "
   331     "
   332     An implementation of java.lang.Object#wait(long). Returns `true`
   332     An implementation of java.lang.Object#wait(long). Returns `true`
   333     after waiting or `false` immediately (i.e., won't block) if calling
   333     after waiting or `false` immediately (i.e., won't block) if calling
   334     thread does not own the monitor.
   334     thread does not own the monitor.
   335 
   335 
   336     See Java API documentation for java.lang.Object#wait(long):
   336     See Java API documentation for java.lang.Object#wait(long):
   337         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long)
   337         https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long)
   338     "
   338     "
   339     
   339 
   340     | thisProcess countBeforeWait |
   340     | active countBeforeWait |
   341     thisProcess := Processor activeProcess.
   341     active := Processor activeProcess.
   342     owningProcess == thisProcess ifFalse:[ 
   342     process == active ifFalse:[
   343         "/ Oops,  calling thread does not own the monitor. return false
   343         "/ Oops,  calling thread does not own the monitor. return false
   344         "/ immediately. The caller is responsible for throwing
   344         "/ immediately. The caller is responsible for throwing
   345         "/ IllegalMonitorStateException...
   345         "/ IllegalMonitorStateException...
   346         ^ false.
   346         ^ false.
   347     ].
   347     ].
   348     self waitEnabled ifFalse: [
   348     self waitEnabled ifFalse: [
   349         JavaVM monitorTrace ifTrue:[
   349         JavaVM monitorTrace ifTrue:[
   350             Logger 
   350             Logger
   351                 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' 
   351                 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead'
   352                         bindWith: thisProcess printString
   352                         bindWith: active printString
   353                         with: ownerPrintString)
   353                         with: ownerPrintString)
   354                 severity: Logger severityDEBUG
   354                 severity: Logger severityDEBUG
   355                 facility: #JVM.
   355                 facility: #JVM.
   356         ].
   356         ].
   357         ^ true.
   357         ^ true.
   358     ].
   358     ].
   359     JavaVM monitorTrace ifTrue:[
   359     JavaVM monitorTrace ifTrue:[
   360         Logger 
   360         Logger
   361             log: ('%1 is going to wait on %3 for timeout: %2' 
   361             log: ('%1 is going to wait on %3 for timeout: %2'
   362                     bindWith: thisProcess printString
   362                     bindWith: active printString
   363                     with: timeOut
   363                     with: timeOut
   364                     with: ownerPrintString printString)
   364                     with: ownerPrintString printString)
   365             severity: #debug
   365             severity: #debug
   366             facility: #JVM.
   366             facility: #JVM.
   367     ].
   367     ].
   374     "/ Monitor released, wait...
   374     "/ Monitor released, wait...
   375      "JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
   375      "JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
   376     timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
   376     timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
   377         waitingSema waitWithTimeoutMs: timeOut
   377         waitingSema waitWithTimeoutMs: timeOut
   378     ].
   378     ].
   379     JavaVM monitorTrace ifTrue:[ 
   379     JavaVM monitorTrace ifTrue:[
   380         Logger 
   380         Logger
   381             log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' 
   381             log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3'
   382                     bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString)
   382                     bindWith: active printString with: ownerPrintString printString with: process printString)
   383             severity: #debug
   383             severity: #debug
   384             facility: #JVM.
   384             facility: #JVM.
   385     ].
   385     ].
   386     "/ We have been notified, re-acquire the monitor
   386     "/ We have been notified, re-acquire the monitor
   387     self acquire.
   387     self acquire.
   393     "Modified (comment): / 14-08-2017 / 09:52:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   393     "Modified (comment): / 14-08-2017 / 09:52:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   394 ! !
   394 ! !
   395 
   395 
   396 !JavaMonitor methodsFor:'queries'!
   396 !JavaMonitor methodsFor:'queries'!
   397 
   397 
   398 isOwnedBy: aProcess 
   398 isOwnedBy: aProcess
   399     ^ owningProcess == aProcess.
   399     ^ process == aProcess.
   400 
   400 
   401     "Created: / 20-11-2011 / 13:23:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   401     "Created: / 20-11-2011 / 13:23:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   402     "Modified: / 12-08-2017 / 21:24:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   402     "Modified: / 12-08-2017 / 21:24:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   403 ! !
   403 ! !
   404 
   404