author | vranyj1 |
Tue, 24 Jul 2012 14:58:23 +0000 | |
branch | jk_new_structure |
changeset 1552 | 89c63e6303f1 |
parent 1551 | 2af2aa41bddb |
child 1553 | ee3e63c04778 |
permissions | -rw-r--r-- |
1548 | 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:#JavaFinalizationRegistry |
|
1551 | 24 |
instanceVariableNames:'activeReferees finalizationSemaphore finalizationProcess' |
1548 | 25 |
classVariableNames:'' |
26 |
poolDictionaries:'' |
|
27 |
category:'Languages-Java-Support' |
|
28 |
! |
|
29 |
||
30 |
!JavaFinalizationRegistry class methodsFor:'documentation'! |
|
31 |
||
32 |
copyright |
|
33 |
" |
|
34 |
COPYRIGHT (c) 1996-2011 by Claus Gittinger |
|
35 |
||
36 |
New code and modifications done at SWING Research Group [1]: |
|
37 |
||
38 |
COPYRIGHT (c) 2010-2011 by Jan Vrany, Jan Kurs and Marcel Hlopko |
|
39 |
SWING Research Group, Czech Technical University in Prague |
|
40 |
||
41 |
This software is furnished under a license and may be used |
|
42 |
only in accordance with the terms of that license and with the |
|
43 |
inclusion of the above copyright notice. This software may not |
|
44 |
be provided or otherwise made available to, or used by, any |
|
45 |
other person. No title to or ownership of the software is |
|
46 |
hereby transferred. |
|
47 |
||
48 |
[1] Code written at SWING Research Group contains a signature |
|
49 |
of one of the above copright owners. For exact set of such code, |
|
50 |
see the differences between this version and version stx:libjava |
|
51 |
as of 1.9.2010 |
|
52 |
||
53 |
" |
|
54 |
! |
|
55 |
||
56 |
documentation |
|
57 |
" |
|
58 |
A tricky class that implements Java-style finalization. |
|
59 |
Future versions may involve some C / VM optimization, |
|
60 |
if this algorithm prooves usefull |
|
61 |
||
62 |
[author:] |
|
63 |
Jan Vrany <jan.vrany@fit.cvut.cz> |
|
64 |
||
65 |
[instance variables:] |
|
66 |
||
67 |
[class variables:] |
|
68 |
||
69 |
[see also:] |
|
70 |
||
71 |
" |
|
72 |
! ! |
|
73 |
||
74 |
!JavaFinalizationRegistry class methodsFor:'instance creation'! |
|
75 |
||
76 |
new |
|
77 |
"return an initialized instance" |
|
78 |
||
79 |
^ self basicNew initialize. |
|
80 |
! ! |
|
81 |
||
1551 | 82 |
!JavaFinalizationRegistry methodsFor:'finalization'! |
1548 | 83 |
|
1551 | 84 |
finalizationCycle |
1548 | 85 |
|
1549 | 86 |
| referees references living wasBlocked firstPendingReference lastPendingReference ref | |
1548 | 87 |
|
1549 | 88 |
referees := (activeReferees select:[:e|e notNil]) asArray. |
1548 | 89 |
references := Array new: referees size. |
90 |
living := Array new: referees size. |
|
91 |
firstPendingReference := nil. |
|
92 |
||
93 |
ObjectMemory allObjectsIncludingContextsDo:[:o| |
|
94 |
| index | |
|
1549 | 95 |
(o ~~ referees and:[o ~~ activeReferees]) ifTrue:[ |
96 |
(index := self references: o anyOf: referees) ~~ 0 ifTrue:[ |
|
97 |
o class name == #'java/lang/ref/Finalizer' ifTrue:[ |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
98 |
self assert: (self getNextOf: o) isNil. |
1549 | 99 |
references at: index put: o |
100 |
] ifFalse:[ |
|
101 |
living at: index put: o. |
|
102 |
] |
|
103 |
]. |
|
1548 | 104 |
]. |
105 |
]. |
|
106 |
||
107 |
wasBlocked := OperatingSystem blockInterrupts. |
|
108 |
||
109 |
living withIndexDo:[:each :index| |
|
1549 | 110 |
each isNil ifTrue:[ |
1548 | 111 |
ref := references at: index. |
1549 | 112 |
activeReferees at: (activeReferees identityIndexOf: (referees at: index)) put: nil. |
1548 | 113 |
firstPendingReference isNil ifTrue:[ |
114 |
firstPendingReference := lastPendingReference := ref |
|
115 |
] ifFalse:[ |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
116 |
self setNextOf: lastPendingReference to: ref. |
1548 | 117 |
lastPendingReference := ref. |
118 |
]. |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
119 |
self setNextOf: lastPendingReference to: lastPendingReference |
1548 | 120 |
]. |
121 |
]. |
|
1549 | 122 |
wasBlocked ifFalse:[ OperatingSystem unblockInterrupts]. |
123 |
||
124 |
self informReferenceHandler: firstPendingReference |
|
1548 | 125 |
|
1551 | 126 |
"Created: / 24-07-2012 / 15:14:50 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
1548 | 127 |
! |
128 |
||
1551 | 129 |
finalizationLoop |
130 |
||
131 |
[ |
|
132 |
finalizationSemaphore waitWithTimeoutMs: 10000"10sec". |
|
133 |
self finalizationCycle |
|
134 |
] loop |
|
135 |
||
136 |
"Created: / 24-07-2012 / 15:16:51 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
137 |
! ! |
|
138 |
||
139 |
!JavaFinalizationRegistry methodsFor:'initialization'! |
|
140 |
||
141 |
initialize |
|
142 |
"Invoked when a new instance is created." |
|
143 |
||
144 |
"/ please change as required (and remove this comment) |
|
145 |
activeReferees := Array new: 200. |
|
146 |
"/ super initialize. -- commented since inherited method does nothing |
|
147 |
||
148 |
"Modified: / 24-07-2012 / 15:23:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
149 |
! ! |
|
150 |
||
151 |
!JavaFinalizationRegistry methodsFor:'private'! |
|
152 |
||
1548 | 153 |
firstFreeIndex |
154 |
activeReferees withIndexDo:[:value :index| |
|
155 |
value isNil ifTrue:[ |
|
156 |
^index |
|
157 |
]. |
|
158 |
]. |
|
159 |
self grow. |
|
1552 | 160 |
activeReferees withIndexDo:[:value :index| |
161 |
value isNil ifTrue:[ |
|
162 |
^index |
|
163 |
]. |
|
164 |
]. |
|
165 |
JavaVM internalError: 'No free finalization slot even after grow'. |
|
1548 | 166 |
|
167 |
"Created: / 24-07-2012 / 01:19:57 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
168 |
! |
|
169 |
||
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
170 |
getNextOf: reference |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
171 |
|
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
172 |
^reference instVarAt: 3 |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
173 |
|
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
174 |
"Created: / 24-07-2012 / 11:22:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
175 |
! |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
176 |
|
1548 | 177 |
grow |
178 |
||
1552 | 179 |
| newActiveReferees | |
180 |
newActiveReferees := Array new: activeReferees size * 2. |
|
181 |
newActiveReferees replaceFrom: 1 with: activeReferees. |
|
182 |
activeReferees := newActiveReferees |
|
1548 | 183 |
|
184 |
"Created: / 24-07-2012 / 01:20:09 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
185 |
! |
|
186 |
||
1549 | 187 |
informReferenceHandler: reference |
188 |
| referenceClass lock | |
|
189 |
||
190 |
reference isNil ifTrue:[ ^ self ]. |
|
191 |
||
192 |
referenceClass := Java classForName: 'java.lang.ref.Reference'. |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
193 |
lock := JavaVM monitorFor: (referenceClass instVarNamed: #lock). |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
194 |
|
1549 | 195 |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
196 |
lock enter. |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
197 |
[ |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
198 |
referenceClass instVarNamed: #pending put: reference. |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
199 |
lock notify. |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
200 |
] ensure:[ |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
201 |
lock exit. |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
202 |
]. |
1549 | 203 |
|
204 |
"Created: / 24-07-2012 / 03:42:37 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
205 |
! |
|
206 |
||
207 |
references: object anyOf: aCollection |
|
1548 | 208 |
"If object references any object in a collection, return |
209 |
index of value which it references, zero otherwise" |
|
210 |
||
1549 | 211 |
%{ |
212 |
OBJ cls, flags; |
|
213 |
int nInsts, inst; |
|
214 |
if (! __isNonNilObject(object)) { |
|
215 |
RETURN (__MKINT(0)); |
|
216 |
} |
|
217 |
||
218 |
if (__isArrayLike(aCollection)) { |
|
219 |
int nObjs = __arraySize(aCollection); |
|
220 |
char *minAddr = 0, *maxAddr = 0; |
|
221 |
||
222 |
if (nObjs == 0) { |
|
223 |
RETURN (__MKINT(0)); |
|
224 |
} |
|
225 |
||
226 |
/* |
|
227 |
* a little optimization: use the fact that all old objects |
|
228 |
* refering to a new object are on the remSet; if I am not, |
|
229 |
* a trivial reject is possible, if all objects are newbees. |
|
230 |
* as a side effect, gather min/max addresses |
|
231 |
*/ |
|
232 |
if ((__qSpace(object) <= OLDSPACE) && !__isRemembered(object)) { |
|
233 |
int allNewBees = 1; |
|
234 |
int i; |
|
235 |
||
236 |
minAddr = (char *)(__ArrayInstPtr(aCollection)->a_element[0]); |
|
237 |
maxAddr = minAddr; |
|
238 |
||
239 |
for (i=0; i<nObjs; i++) { |
|
240 |
OBJ anObject; |
|
241 |
||
242 |
anObject = __ArrayInstPtr(aCollection)->a_element[i]; |
|
243 |
||
244 |
if (__isNonNilObject(anObject)) { |
|
245 |
int spc; |
|
246 |
||
247 |
if (((spc = __qSpace(anObject)) != NEWSPACE) && (spc != SURVSPACE)) { |
|
248 |
allNewBees = 0; |
|
249 |
} |
|
250 |
} |
|
251 |
||
252 |
if ((char *)anObject < minAddr) { |
|
253 |
minAddr = (char *)anObject; |
|
254 |
} else if ((char *)anObject > maxAddr) { |
|
255 |
maxAddr = (char *)anObject; |
|
256 |
} |
|
257 |
} |
|
258 |
if (allNewBees) { |
|
259 |
RETURN (__MKINT(0)); |
|
260 |
} |
|
261 |
} |
|
262 |
||
263 |
/* |
|
264 |
* fetch min/max in searchList (if not already done) |
|
265 |
*/ |
|
266 |
if (minAddr == 0) { |
|
267 |
int i; |
|
1548 | 268 |
|
1549 | 269 |
for (i=0; i<nObjs; i++) { |
270 |
OBJ anObject; |
|
271 |
||
272 |
anObject = __ArrayInstPtr(aCollection)->a_element[i]; |
|
273 |
if ((char *)anObject < minAddr) { |
|
274 |
minAddr = (char *)anObject; |
|
275 |
} else if ((char *)anObject > maxAddr) { |
|
276 |
maxAddr = (char *)anObject; |
|
277 |
} |
|
278 |
} |
|
279 |
} |
|
280 |
||
281 |
cls = __qClass(object); |
|
282 |
flags = __ClassInstPtr(cls)->c_flags; |
|
283 |
if (((INT)flags & __MASKSMALLINT(ARRAYMASK)) == __MASKSMALLINT(POINTERARRAY)) { |
|
284 |
nInsts = __BYTES2OBJS__(__qSize(object) - OHDR_SIZE); |
|
285 |
} else { |
|
286 |
nInsts = __intVal(__ClassInstPtr(cls)->c_ninstvars); |
|
287 |
} |
|
288 |
if (! nInsts) { |
|
289 |
RETURN (__MKINT(0)); |
|
290 |
} |
|
291 |
||
292 |
if (nObjs == 1) { |
|
293 |
/* better reverse the loop */ |
|
294 |
OBJ anObject; |
|
295 |
||
296 |
anObject = __ArrayInstPtr(aCollection)->a_element[0]; |
|
297 |
#if defined(memsrch4) |
|
298 |
if (memsrch4(__InstPtr(object)->i_instvars, (INT)anObject, nInsts)) { |
|
299 |
RETURN (__MKINT(1)); |
|
300 |
} |
|
301 |
#else |
|
302 |
for (inst=0; inst<nInsts; inst++) { |
|
303 |
if ((__InstPtr(object)->i_instvars[inst]) == anObject) { |
|
304 |
RETURN (__MKINT(1)); |
|
305 |
} |
|
306 |
} |
|
307 |
#endif |
|
308 |
RETURN (false); |
|
309 |
} |
|
310 |
||
311 |
for (inst=0; inst<nInsts; inst++) { |
|
312 |
OBJ instVar = __InstPtr(object)->i_instvars[inst]; |
|
313 |
int i; |
|
314 |
||
315 |
if (((char *)instVar >= minAddr) && ((char *)instVar <= maxAddr)) { |
|
316 |
for (i=0; i<nObjs; i++) { |
|
317 |
OBJ anObject; |
|
318 |
||
319 |
anObject = __ArrayInstPtr(aCollection)->a_element[i]; |
|
320 |
if (instVar == anObject) { |
|
321 |
RETURN (__MKINT(i+1)); |
|
322 |
} |
|
323 |
} |
|
324 |
} |
|
325 |
} |
|
326 |
RETURN (__MKINT(0)); |
|
327 |
} |
|
328 |
%}. |
|
329 |
||
330 |
aCollection withIndexDo:[:each :eachi| |
|
1548 | 331 |
(object references: each) ifTrue:[^eachi]. |
332 |
]. |
|
333 |
^0 |
|
334 |
||
335 |
"Created: / 24-07-2012 / 01:49:50 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
1550
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
336 |
! |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
337 |
|
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
338 |
setNextOf: reference to: value |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
339 |
|
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
340 |
^reference instVarAt: 3 put: value |
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
341 |
|
fde50161f2b4
- more finalization stuff. The only missing bit is periodical call to collectionCycle...
vranyj1
parents:
1549
diff
changeset
|
342 |
"Created: / 24-07-2012 / 11:22:21 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
1548 | 343 |
! ! |
344 |
||
345 |
!JavaFinalizationRegistry methodsFor:'registering objects'! |
|
346 |
||
347 |
register: object |
|
348 |
"Register an object for being finalized" |
|
349 |
||
350 |
| index finalizedClass | |
|
351 |
index := self firstFreeIndex. |
|
352 |
activeReferees at: index put: object. |
|
1549 | 353 |
finalizedClass := Java classForName:'java.lang.ref.Finalizer'. |
354 |
finalizedClass classInit. |
|
355 |
(finalizedClass methodDictionary at: #'register(Ljava/lang/Object;)V') |
|
1548 | 356 |
valueWithReceiver: finalizedClass arguments: (Array with: object) |
357 |
||
358 |
"Created: / 24-07-2012 / 01:14:26 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
1551 | 359 |
! |
360 |
||
361 |
registerChange: anObject |
|
362 |
"/Nothing to do, to be polymprph with Registry" |
|
363 |
||
364 |
"Created: / 24-07-2012 / 03:31:18 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
365 |
! ! |
|
366 |
||
367 |
!JavaFinalizationRegistry methodsFor:'start & stop'! |
|
368 |
||
369 |
startFinalizationProcessAt:aPriority |
|
370 |
||
371 |
|p| |
|
372 |
||
373 |
finalizationProcess notNil ifTrue:[ |
|
374 |
finalizationProcess priority:aPriority. |
|
375 |
^ self |
|
376 |
]. |
|
377 |
||
378 |
finalizationSemaphore := Semaphore new name:'FinalizationSemaphore (Java)'. |
|
379 |
||
380 |
p := |
|
381 |
[ |
|
382 |
[ |
|
383 |
self finalizationLoop |
|
384 |
] ifCurtailed:[ |
|
385 |
finalizationProcess := nil. |
|
386 |
finalizationSemaphore := nil |
|
387 |
] |
|
388 |
] newProcess. |
|
389 |
p name:'background finalizer (Java)'. |
|
390 |
p priority:aPriority. |
|
391 |
p restartable:true. |
|
392 |
p beSystemProcess. |
|
393 |
p resume. |
|
394 |
finalizationProcess := p |
|
395 |
||
396 |
"Created: / 24-07-2012 / 15:25:06 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
397 |
! |
|
398 |
||
399 |
stopFinalizationProcess |
|
400 |
"stop the background finalizer" |
|
401 |
||
402 |
finalizationProcess notNil ifTrue:[ |
|
403 |
finalizationProcess terminate. |
|
404 |
finalizationProcess := nil |
|
405 |
]. |
|
406 |
||
407 |
"Created: / 24-07-2012 / 15:26:38 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
408 |
! ! |
|
409 |
||
410 |
!JavaFinalizationRegistry methodsFor:'utilities'! |
|
411 |
||
412 |
finalizeNow |
|
413 |
"Force finalization to run now" |
|
414 |
finalizationSemaphore signal |
|
415 |
||
416 |
"Created: / 24-07-2012 / 15:28:45 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
1548 | 417 |
! ! |
418 |
||
419 |
!JavaFinalizationRegistry class methodsFor:'documentation'! |
|
420 |
||
421 |
version_SVN |
|
422 |
^ '$Id:: $' |
|
423 |
! ! |