JavaMonitor.st
changeset 3778 2297f9daef8a
parent 3777 971961e59d5e
child 3779 973f2396c750
equal deleted inserted replaced
3777:971961e59d5e 3778:2297f9daef8a
   175 ! !
   175 ! !
   176 
   176 
   177 !JavaMonitor methodsFor:'public'!
   177 !JavaMonitor methodsFor:'public'!
   178 
   178 
   179 acquire
   179 acquire
   180     | thisProcess |
   180     | thisProcess wasBlocked hasAcquired |
   181     thisProcess := Processor activeProcess.
   181     hasAcquired := nil.
   182     (self isOwnedBy: thisProcess) ifTrue: [
   182     thisProcess := Processor activeProcess.
   183         "/ the lock is probably not helping here to protect against problems with
   183     owningProcess == thisProcess ifTrue:[ 
   184         "/ increment/decrement:
   184         "/ Process already ackquired the monitor, increase the
   185         "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
   185         "/ count and continue...
   186         "/ if after, everything is ok;
   186         count := count + 1.
   187         "/ if before, the decremented value will be zero, which is probably wrong.
   187         ^self.
   188 
   188     ].
   189         "/ without the critical region, we might also get possible inconsistencies:
   189     wasBlocked := OperatingSystem blockInterrupts.
   190         "/ if written before, the counter will drop to zero
   190     [ 
   191         "/ if written in-between, the counter wil ahve the old value decremented;
   191         (owningProcess notNil and:[ owningProcess isDead ]) ifTrue:[ 
   192         "/ if written afterwards, everything is ok.
   192             "/ Process that acquired the monitor died without releasing it.
   193 
   193             "/ This should not happen.
   194         "/ so, the lock should be really elsewhere, making sure that noone will count
   194             wasBlocked ifFalse:[OperatingSystem unblockInterrupts].    
   195         "/ the monitor at-all and the monitor is reininialized without anyone depending on the
   195             self assert: false description: 'Process that acquired the monitor died without releasing it'.
   196         "/ count at all.
   196             owningProcess := nil.
   197         "/ but then, no critical section is needed in reinitCounter!!.
   197             count := 0.
   198 
   198         ].
   199         self instVarAccessCritical: [ count := count + 1 ].
   199         "/ We need to know that we already waited on and got semaphore
   200         ^ self
   200         "/ in case the Semaphore >> #wait is prematurely terminated.
   201     ].
   201         "/ Q: Can this actually happen? If so, how?
   202     monitorSema wait.
   202         hasAcquired := monitorSema wait. 
   203     owningProcess := thisProcess. 
   203         owningProcess := thisProcess.
   204     count := 1.
   204         count := 1.
       
   205         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].
       
   206     ] ifCurtailed:[
       
   207         hasAcquired notNil ifTrue:[
       
   208             OperatingSystem blockInterrupts.
       
   209             count := 0.
       
   210             owningProcess := nil.
       
   211             monitorSema signal.
       
   212         ].
       
   213         wasBlocked ifFalse:[OperatingSystem unblockInterrupts].       
       
   214     ]
   205 
   215 
   206     "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   216     "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   207     "Modified: / 03-06-2017 / 22:36:04 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   217     "Modified: / 11-08-2017 / 22:08:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   208 !
   218 !
   209 
   219 
   210 enter
   220 enter
   211     self acquire.
   221     self acquire.
   212 
   222 
   230 notify
   240 notify
   231     "wakeup one waiting process"
   241     "wakeup one waiting process"
   232     
   242     
   233     | thisProcess |
   243     | thisProcess |
   234     thisProcess := Processor activeProcess.
   244     thisProcess := Processor activeProcess.
   235     self assert: (self isOwnedBy: thisProcess).
   245     self assert: owningProcess == thisProcess.
   236     JavaVM monitorTrace ifTrue:[
   246     JavaVM monitorTrace ifTrue:[
   237         Logger 
   247         Logger 
   238             log: ('%1: notifying %2 processes' bindWith: thisProcess printString
   248             log: ('%1: notifying %2 processes' bindWith: thisProcess printString
   239                     with: waitingSema waitingProcesses size)
   249                     with: waitingSema waitingProcesses size)
   240             severity: Logger severityDEBUG
   250             severity: Logger severityDEBUG
   242     ].
   252     ].
   243     waitingSema signal.
   253     waitingSema signal.
   244     Processor yield.
   254     Processor yield.
   245 
   255 
   246     "Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   256     "Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   247     "Modified: / 05-05-2017 / 17:27:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   257     "Modified: / 11-08-2017 / 22:25:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   248 !
   258 !
   249 
   259 
   250 notifyAll
   260 notifyAll
   251     "wakeup one waiting process"
   261     "wakeup one waiting process"
   252     
   262     
   253     | thisProcess |
   263     | thisProcess |
   254     thisProcess := Processor activeProcess.
   264     thisProcess := Processor activeProcess.
   255     self assert: (self isOwnedBy: thisProcess).
   265     self assert: owningProcess == thisProcess.
   256     JavaVM monitorTrace ifTrue:[
   266     JavaVM monitorTrace ifTrue:[
   257         Logger 
   267         Logger 
   258             log: ('%1: notifying all %2 processes' bindWith: thisProcess printString
   268             log: ('%1: notifying all %2 processes' bindWith: thisProcess printString
   259                     with: waitingSema waitingProcesses size)
   269                     with: waitingSema waitingProcesses size)
   260             severity: Logger severityDEBUG
   270             severity: Logger severityDEBUG
   262     ].
   272     ].
   263     waitingSema signalForAll.
   273     waitingSema signalForAll.
   264     Processor yield.
   274     Processor yield.
   265 
   275 
   266     "Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   276     "Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   267     "Modified: / 05-05-2017 / 17:28:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   277     "Modified: / 11-08-2017 / 22:26:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   268 !
   278 !
   269 
   279 
   270 release
   280 release
       
   281     | wasBlocked |
       
   282 
   271     self assert: (self isOwnedBy: owningProcess).
   283     self assert: (self isOwnedBy: owningProcess).
   272     count == 1 ifTrue: [
   284     wasBlocked := OperatingSystem blockInterrupts.
   273         self instVarAccessCritical: [ owningProcess := nil ].  
   285     count == 1 ifTrue:[ 
       
   286         owningProcess := nil.
   274         count := 0.
   287         count := 0.
   275         monitorSema signal.
   288         monitorSema signal.
   276     ] ifFalse: [
   289     ] ifFalse:[ 
   277         "/ the lock is probably not helping here to protect against problems with
   290         count := count - 1.
   278         "/ increment/decrement:
   291     ].
   279         "/ the write-access (in reinitCOunter) will be either done before incrementing/decrementing or after.
   292     OperatingSystem unblockInterrupts.
   280         "/ if after, everything is ok;
       
   281         "/ if before, the decremented value will be zero, which is probably wrong.
       
   282 
       
   283         "/ without the critical region, we might also get possible inconsistencies:
       
   284         "/ if written before, the counter will drop to zero
       
   285         "/ if written in-between, the counter wil ahve the old value decremented;
       
   286         "/ if written afterwards, everything is ok.
       
   287 
       
   288         "/ so, the lock should be really elsewhere, making sure that noone will count
       
   289         "/ the monitor at-all and the monitor is reininialized without anyone depending on the
       
   290         "/ count at all.
       
   291         "/ but then, no critical section is needed in reinitCounter!!.
       
   292 
       
   293         self instVarAccessCritical: [ count := count - 1 ].
       
   294     ]
       
   295 
   293 
   296     "Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   294     "Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   297     "Modified: / 03-06-2017 / 22:24:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   295     "Modified: / 11-08-2017 / 22:18:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   298 !
   296 !
   299 
   297 
   300 wait
   298 wait
   301     "make owning process to go to wait"
   299     "make owning process to go to wait"
   302     
   300     
   308 waitForMilliseconds: timeOut 
   306 waitForMilliseconds: timeOut 
   309     "make owning process to go to wait, but not longer than timeout"
   307     "make owning process to go to wait, but not longer than timeout"
   310     
   308     
   311     | thisProcess countBeforeWait |
   309     | thisProcess countBeforeWait |
   312     thisProcess := Processor activeProcess.
   310     thisProcess := Processor activeProcess.
   313     self assert: (self isOwnedBy: thisProcess).
   311     self assert: owningProcess == thisProcess.
   314     self waitEnabled ifFalse: [
   312     self waitEnabled ifFalse: [
   315         JavaVM monitorTrace ifTrue:[
   313         JavaVM monitorTrace ifTrue:[
   316             Logger 
   314             Logger 
   317                 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' 
   315                 log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' 
   318                         bindWith: thisProcess printString
   316                         bindWith: thisProcess printString
   329                     with: timeOut
   327                     with: timeOut
   330                     with: ownerPrintString printString)
   328                     with: ownerPrintString printString)
   331             severity: #debug
   329             severity: #debug
   332             facility: #JVM.
   330             facility: #JVM.
   333     ].
   331     ].
   334     countBeforeWait :=  count.
   332     countBeforeWait := count.
   335     count timesRepeat: [self release].
   333     "/ Release the monitor so other thread can acquire it
       
   334     "/ and call #notify or #notifyAll
       
   335     count := 1. "/ note that at this point we still own the monitor
       
   336     self release.
       
   337 
       
   338     "/ Monitor released, wait...
   336      "JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
   339      "JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
   337     timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
   340     timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
   338         waitingSema waitWithTimeoutMs: timeOut
   341         waitingSema waitWithTimeoutMs: timeOut
   339     ].
   342     ].
   340     JavaVM monitorTrace ifTrue:[ 
   343     JavaVM monitorTrace ifTrue:[ 
   342             log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' 
   345             log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' 
   343                     bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString)
   346                     bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString)
   344             severity: #debug
   347             severity: #debug
   345             facility: #JVM.
   348             facility: #JVM.
   346     ].
   349     ].
       
   350     "/ We have been notified, re-acquire the monitor
   347     self acquire.
   351     self acquire.
   348     count := countBeforeWait.
   352     count := countBeforeWait. "/ note that at this point we already own the monitor
   349 
   353 
   350     "Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   354     "Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   351     "Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   355     "Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
   352     "Modified: / 03-06-2017 / 22:52:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   356     "Modified: / 11-08-2017 / 23:04:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
   353 ! !
   357 ! !
   354 
   358 
   355 !JavaMonitor methodsFor:'queries'!
   359 !JavaMonitor methodsFor:'queries'!
   356 
   360 
   357 isAcquired
   361 isAcquired