JavaMonitor.st
branchdirectory_structure_refactoring
changeset 1818 2e5ed72e7dfd
parent 1691 826f8d7dc0df
child 1864 60a8dc26c8c6
equal deleted inserted replaced
1817:b86c40afbf1f 1818:2e5ed72e7dfd
       
     1 "
       
     2  COPYRIGHT (c) 1996-2011 by Claus Gittinger
       
     3 
       
     4  New code and modifications done at SWING Research Group [1]:
       
     5 
       
     6  COPYRIGHT (c) 2010-2011 by Jan Vrany, Jan Kurs and Marcel Hlopko
       
     7                             SWING Research Group, Czech Technical University in Prague
       
     8 
       
     9  This software is furnished under a license and may be used
       
    10  only in accordance with the terms of that license and with the
       
    11  inclusion of the above copyright notice.   This software may not
       
    12  be provided or otherwise made available to, or used by, any
       
    13  other person.  No title to or ownership of the software is
       
    14  hereby transferred.
       
    15 
       
    16  [1] Code written at SWING Research Group contains a signature
       
    17      of one of the above copright owners. For exact set of such code,
       
    18      see the differences between this version and version stx:libjava
       
    19      as of 1.9.2010
       
    20 "
       
    21 "{ Package: 'stx:libjava' }"
       
    22 
       
    23 Object subclass:#JavaMonitor
       
    24 	instanceVariableNames:'owningProcess processesEntered monitorSema count waitingSema
       
    25 		processesWaiting waitEnabled ownerPrintString'
       
    26 	classVariableNames:'instVarAccess'
       
    27 	poolDictionaries:''
       
    28 	category:'Languages-Java-Support'
       
    29 !
       
    30 
       
    31 !JavaMonitor class methodsFor:'documentation'!
       
    32 
       
    33 copyright
       
    34 "
       
    35  COPYRIGHT (c) 1996-2011 by Claus Gittinger
       
    36 
       
    37  New code and modifications done at SWING Research Group [1]:
       
    38 
       
    39  COPYRIGHT (c) 2010-2011 by Jan Vrany, Jan Kurs and Marcel Hlopko
       
    40                             SWING Research Group, Czech Technical University in Prague
       
    41 
       
    42  This software is furnished under a license and may be used
       
    43  only in accordance with the terms of that license and with the
       
    44  inclusion of the above copyright notice.   This software may not
       
    45  be provided or otherwise made available to, or used by, any
       
    46  other person.  No title to or ownership of the software is
       
    47  hereby transferred.
       
    48 
       
    49  [1] Code written at SWING Research Group contains a signature
       
    50      of one of the above copright owners. For exact set of such code,
       
    51      see the differences between this version and version stx:libjava
       
    52      as of 1.9.2010
       
    53 
       
    54 "
       
    55 ! !
       
    56 
       
    57 !JavaMonitor class methodsFor:'initialization'!
       
    58 
       
    59 initialize
       
    60 instVarAccess := RecursionLock forMutualExclusion.
       
    61 
       
    62     "Created: / 29-11-2011 / 11:23:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
    63 ! !
       
    64 
       
    65 !JavaMonitor class methodsFor:'instance creation'!
       
    66 
       
    67 for: owningObject
       
    68     ^ self basicNew initializeFor: owningObject.
       
    69 
       
    70     "Created: / 30-11-2011 / 20:39:55 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
    71 !
       
    72 
       
    73 for: owningObject thread: threadOrNil nestedLockCount: count
       
    74     ^ self basicNew initializeFor: owningObject thread: threadOrNil nestedLockCount: count
       
    75 
       
    76     "Created: / 26-08-2012 / 17:01:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
    77 ! !
       
    78 
       
    79 !JavaMonitor methodsFor:'accessing'!
       
    80 
       
    81 activeProcess
       
    82     ^ Processor activeProcess
       
    83 !
       
    84 
       
    85 copyProcessesEntered
       
    86     ^ processesEntered copy.
       
    87 
       
    88     "Created: / 20-11-2011 / 14:45:24 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
    89 !
       
    90 
       
    91 count
       
    92     ^ count
       
    93 !
       
    94 
       
    95 processesEntered
       
    96     "dont do anything to me, access needs to be sync'd"
       
    97     ^ processesEntered.
       
    98 
       
    99     "Created: / 20-11-2011 / 13:22:15 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   100 ! !
       
   101 
       
   102 !JavaMonitor methodsFor:'atomic'!
       
   103 
       
   104 addProcess: aProcess 
       
   105     instVarAccess critical: [ processesEntered add: aProcess ].
       
   106 
       
   107     "Created: / 20-11-2011 / 20:30:07 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   108 !
       
   109 
       
   110 clearOwningProcess
       
   111     instVarAccess critical: [ owningProcess := nil ].
       
   112 
       
   113     "Created: / 20-11-2011 / 20:34:27 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   114 !
       
   115 
       
   116 decrement
       
   117     "owning process released monitor, lets lower our counter so we know how many times
       
   118      do we have to release it"
       
   119     
       
   120     instVarAccess critical: [ count := count - 1 ].
       
   121 
       
   122     "Created: / 22-11-2011 / 10:49:33 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   123 !
       
   124 
       
   125 disableWait
       
   126     Logger log: ('Waiting is disabled on monitor for %1' bindWith: ownerPrintString) severity:#debug facility:#JVM.
       
   127     instVarAccess critical: [ waitEnabled := false ].
       
   128 
       
   129     "Created: / 30-11-2011 / 20:34:40 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   130     "Modified: / 10-05-2012 / 00:24:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   131 !
       
   132 
       
   133 enableWait
       
   134 instVarAccess critical: [waitEnabled := true].
       
   135 
       
   136     "Created: / 30-11-2011 / 20:34:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   137 !
       
   138 
       
   139 increment
       
   140     "owning process entered monitor again (recursion ...), lets raise our counter so we know how many times
       
   141      do we have to release it"
       
   142     
       
   143     instVarAccess critical: [ count := count + 1 ].
       
   144 
       
   145     "Created: / 22-11-2011 / 10:49:07 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   146     "Modified: / 27-08-2012 / 10:42:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   147 !
       
   148 
       
   149 owningProcess: aProcess 
       
   150     instVarAccess critical: [ owningProcess := aProcess ].
       
   151 
       
   152     "Created: / 20-11-2011 / 20:32:26 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   153 !
       
   154 
       
   155 processesWaitingAdd: aProcess 
       
   156     instVarAccess 
       
   157         critical: [
       
   158             self assert: (processesWaiting includesKey: aProcess) not.
       
   159             processesWaiting at: aProcess put: count
       
   160         ].
       
   161 
       
   162     "Created: / 22-11-2011 / 11:57:50 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   163 !
       
   164 
       
   165 processesWaitingRestore: aProcess 
       
   166     instVarAccess 
       
   167         critical: [
       
   168             self assert: (processesWaiting includesKey: aProcess).
       
   169             self reinitCounter: (processesWaiting at: aProcess).
       
   170             processesWaiting removeKey: aProcess
       
   171         ].
       
   172 
       
   173     "Created: / 22-11-2011 / 12:59:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   174 !
       
   175 
       
   176 reinitCounter
       
   177     "owning process is different from previous, lets start counting from beginning"
       
   178     
       
   179     instVarAccess critical: [ count := 1 ].
       
   180 
       
   181     "Created: / 22-11-2011 / 10:51:09 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   182 !
       
   183 
       
   184 reinitCounter: newCount 
       
   185     instVarAccess critical: [ count := newCount ].
       
   186 
       
   187     "Created: / 22-11-2011 / 13:00:51 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   188 !
       
   189 
       
   190 removeProcess: aProcess 
       
   191     instVarAccess 
       
   192         critical: [
       
   193             self assert: processesEntered last == aProcess.
       
   194             processesEntered remove: aProcess
       
   195         ].
       
   196 
       
   197     "Created: / 20-11-2011 / 20:28:37 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   198 !
       
   199 
       
   200 waitEnabled
       
   201     instVarAccess critical: [ ^ waitEnabled].
       
   202 
       
   203     "Created: / 30-11-2011 / 20:34:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   204 ! !
       
   205 
       
   206 !JavaMonitor methodsFor:'initialization'!
       
   207 
       
   208 initialize
       
   209     owningProcess := nil.
       
   210     processesEntered := OrderedCollection new.
       
   211     monitorSema := Semaphore new: 1.
       
   212     processesWaiting := Dictionary new.
       
   213     waitingSema := Semaphore new: 0.
       
   214     waitEnabled.
       
   215 
       
   216     "Created: / 20-11-2011 / 13:28:28 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   217 !
       
   218 
       
   219 initializeFor: owningObject
       
   220     self initializeFor: owningObject thread: 0 nestedLockCount: 0.
       
   221 
       
   222     "Created: / 30-11-2011 / 20:39:31 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   223     "Modified: / 26-08-2012 / 17:25:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   224 !
       
   225 
       
   226 initializeFor:owningObject thread:threadId nestedLockCount:cnt 
       
   227 
       
   228 "/    self assert: (owningObject isJavaObject or:[owningObject isJavaClass]).
       
   229 
       
   230     processesEntered := OrderedCollection new.
       
   231     waitEnabled := true.
       
   232     processesWaiting := Dictionary new.
       
   233     waitingSema := Semaphore new:0.
       
   234     ownerPrintString := owningObject class name , '@' , owningObject identityHash printString.
       
   235 
       
   236     "/Not locked...    
       
   237     threadId == 0 ifTrue:[
       
   238         monitorSema := Semaphore new:1.
       
   239         count := 0.
       
   240         ^self.
       
   241     ] ifFalse: [
       
   242         "threadId is not zero (zero is threadId of scheduler process, which will never try to acquire the monitor)"
       
   243         "so it means it is possible that the thin lock is already locked for other thread, we must be careful " 
       
   244 
       
   245         owningProcess := Process findProcessWithId:threadId.
       
   246         self assert: owningProcess notNil.
       
   247         processesEntered add: owningProcess.  
       
   248         cnt timesRepeat:[
       
   249 "/            JavaVM enteredMonitorsOf:  owningProcess add: owningObject.
       
   250 "/            JavaVM acquiredMonitorsOf: owningProcess add: owningObject.
       
   251         ].
       
   252         monitorSema := Semaphore new: 0.
       
   253         count := cnt.
       
   254     ].
       
   255 
       
   256     "Created: / 26-08-2012 / 17:02:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   257 ! !
       
   258 
       
   259 !JavaMonitor methodsFor:'public'!
       
   260 
       
   261 acquire
       
   262     | thisProcess |
       
   263     thisProcess := self activeProcess.
       
   264     (self isOwnedBy: thisProcess) ifTrue: [
       
   265         self increment.
       
   266         ^ self
       
   267     ].
       
   268     monitorSema wait.
       
   269     self owningProcess: thisProcess.
       
   270     count := 1.
       
   271 
       
   272     "Created: / 20-11-2011 / 13:21:46 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   273     "Modified: / 27-08-2012 / 11:45:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   274 !
       
   275 
       
   276 enter
       
   277     | thisProcess |
       
   278     thisProcess := self activeProcess.
       
   279     self addProcess: thisProcess.
       
   280     self acquire.
       
   281 
       
   282     "Created: / 20-11-2011 / 13:21:42 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   283 !
       
   284 
       
   285 exit
       
   286     | thisProcess |
       
   287     thisProcess := self activeProcess.
       
   288     (self isOwnedBy: thisProcess) ifTrue: [ self release. ].    
       
   289     processesEntered remove: thisProcess ifAbsent: nil.
       
   290 
       
   291     "Created: / 20-11-2011 / 13:21:54 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   292     "Modified: / 26-08-2012 / 19:54:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   293 !
       
   294 
       
   295 notify
       
   296     "wakeup one waiting process"
       
   297     
       
   298     | thisProcess |
       
   299     thisProcess := Processor activeProcess.
       
   300     self assert: (self isOwnedBy: thisProcess).
       
   301     Logger 
       
   302         log: ('%1: notifying %2 processes' bindWith: thisProcess printString
       
   303                 with: processesWaiting size)
       
   304         severity: #debug
       
   305         facility: #JVM.
       
   306     waitingSema signal.
       
   307     Processor yield.
       
   308 
       
   309     "Created: / 22-11-2011 / 12:14:23 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   310 !
       
   311 
       
   312 notifyAll
       
   313     "wakeup one waiting process"
       
   314     
       
   315     | thisProcess |
       
   316     thisProcess := Processor activeProcess.
       
   317     self assert: (self isOwnedBy: thisProcess).
       
   318     Logger 
       
   319         log: ('%1: notifying all %2 processes' bindWith: thisProcess printString
       
   320                 with: processesWaiting size)
       
   321         severity: #debug
       
   322         facility: #JVM.
       
   323     waitingSema signalForAll.
       
   324     Processor yield.
       
   325 
       
   326     "Created: / 22-11-2011 / 12:14:36 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   327 !
       
   328 
       
   329 release
       
   330     | thisProcess |
       
   331     thisProcess := self activeProcess.
       
   332     self assert: (self isOwnedBy: owningProcess).
       
   333     count == 1 ifTrue: [
       
   334         self clearOwningProcess.
       
   335         count := 0.
       
   336         monitorSema signal.
       
   337     ] ifFalse: [
       
   338         self decrement.       
       
   339     ]
       
   340 
       
   341     "Created: / 20-11-2011 / 13:21:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   342     "Modified: / 27-08-2012 / 11:44:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   343 !
       
   344 
       
   345 releaseAll
       
   346     count timesRepeat: [self release].
       
   347 
       
   348     "Created: / 22-11-2011 / 13:05:20 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   349 !
       
   350 
       
   351 wait
       
   352     "make owning process to go to wait"
       
   353     
       
   354     self waitForMilliseconds: nil.
       
   355 
       
   356     "Created: / 22-11-2011 / 11:57:56 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   357 !
       
   358 
       
   359 waitForMilliseconds: timeOut 
       
   360     "make owning process to go to wait, but not longer than timeout"
       
   361     
       
   362     | thisProcess |
       
   363     thisProcess := Processor activeProcess.
       
   364     self assert: (self isOwnedBy: thisProcess).
       
   365     self waitEnabled ifFalse: [
       
   366         Logger 
       
   367             log: ('%1 wanted to go to sleep, but it cant, this monitor is for %2 which is already dead' 
       
   368                     bindWith: thisProcess printString
       
   369                     with: ownerPrintString)
       
   370             severity: #debug
       
   371             facility: #JVM.
       
   372         ^ self.
       
   373     ].
       
   374     Logger 
       
   375         log: ('%1 is going to wait on %3 for timeout: %2' 
       
   376                 bindWith: thisProcess printString
       
   377                 with: timeOut
       
   378                 with: ownerPrintString printString)
       
   379         severity: #debug
       
   380         facility: #JVM.
       
   381     self processesWaitingAdd: thisProcess.
       
   382     self releaseAll.
       
   383      "JV@2011-11-25: zero timeout means wait without timeout!!!!!!"
       
   384     timeOut == 0 ifTrue: [ waitingSema wait ] ifFalse: [
       
   385         waitingSema waitWithTimeoutMs: timeOut
       
   386     ].
       
   387     Logger 
       
   388         log: ('%1 has been notified and is trying to acquire monitor for %2 which is owned by %3' 
       
   389                 bindWith: thisProcess printString with: ownerPrintString printString with: owningProcess printString)
       
   390         severity: #debug
       
   391         facility: #JVM.
       
   392     self acquire.
       
   393     self processesWaitingRestore: thisProcess.
       
   394 
       
   395     "Created: / 22-11-2011 / 12:52:45 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   396     "Modified: / 01-12-2011 / 10:57:52 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   397     "Modified: / 10-05-2012 / 00:24:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
       
   398 ! !
       
   399 
       
   400 !JavaMonitor methodsFor:'queries'!
       
   401 
       
   402 isAcquired
       
   403     ^ instVarAccess critical: [ owningProcess notNil ].
       
   404 
       
   405     "Created: / 20-11-2011 / 13:22:26 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   406 !
       
   407 
       
   408 isOwnedBy: aProcess 
       
   409     ^ instVarAccess critical: [ owningProcess == aProcess ].
       
   410 
       
   411     "Created: / 20-11-2011 / 13:23:14 / Marcel Hlopko <hlopkmar@fel.cvut.cz>"
       
   412 ! !
       
   413 
       
   414 !JavaMonitor class methodsFor:'documentation'!
       
   415 
       
   416 version_SVN
       
   417     ^ '$Id$'
       
   418 ! !
       
   419 
       
   420 JavaMonitor initialize!
       
   421