|
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 |