Lines 307-314
Link Here
|
307 |
public final Node[] getNodes () { |
307 |
public final Node[] getNodes () { |
308 |
//Thread.dumpStack(); |
308 |
//Thread.dumpStack(); |
309 |
//System.err.println(off + "getNodes: " + getNode ()); |
309 |
//System.err.println(off + "getNodes: " + getNode ()); |
|
|
310 |
boolean[] results = new boolean[2]; |
310 |
for (;;) { |
311 |
for (;;) { |
311 |
boolean initialized = isInitialized (); |
312 |
results[1] = isInitialized (); |
|
|
313 |
|
314 |
// initializes the ChildrenArray possibly calls |
315 |
// addNotify if this is for the first time |
316 |
ChildrenArray array = getArray(results); // fils results[0] |
317 |
|
312 |
//System.err.println(off + " initialized: " + initialized); |
318 |
//System.err.println(off + " initialized: " + initialized); |
313 |
// off = off + " "; // NOI18N |
319 |
// off = off + " "; // NOI18N |
314 |
// forbid any modifications to this hierarchy |
320 |
// forbid any modifications to this hierarchy |
Lines 316-322
Link Here
|
316 |
try { |
322 |
try { |
317 |
PR.enterReadAccess (); |
323 |
PR.enterReadAccess (); |
318 |
|
324 |
|
319 |
nodes = computeNodes (); |
325 |
nodes = array.nodes (); |
320 |
} finally { |
326 |
} finally { |
321 |
PR.exitReadAccess (); |
327 |
PR.exitReadAccess (); |
322 |
} |
328 |
} |
Lines 329-338
Link Here
|
329 |
// we computed the nodes, somebody changed them (as a |
335 |
// we computed the nodes, somebody changed them (as a |
330 |
// result of addNotify) => we have to compute them |
336 |
// result of addNotify) => we have to compute them |
331 |
// again |
337 |
// again |
332 |
if (initialized) { |
338 |
if (results[1]) { |
333 |
// otherwise it is ok. |
339 |
// otherwise it is ok. |
334 |
return nodes; |
340 |
return nodes; |
335 |
} |
341 |
} |
|
|
342 |
|
343 |
if (results[0]) { |
344 |
// looks like the result cannot be computed, just give empty one |
345 |
return nodes == null ? new Node[0] : nodes; |
346 |
} |
336 |
} |
347 |
} |
337 |
} |
348 |
} |
338 |
|
349 |
|
Lines 366-372
Link Here
|
366 |
public Node[] getNodes(boolean optimalResult) { |
377 |
public Node[] getNodes(boolean optimalResult) { |
367 |
ChildrenArray arr; |
378 |
ChildrenArray arr; |
368 |
if (optimalResult) { |
379 |
if (optimalResult) { |
369 |
arr = getArray(); |
380 |
arr = getArray(null); |
370 |
findChild(null); |
381 |
findChild(null); |
371 |
} |
382 |
} |
372 |
return getNodes(); |
383 |
return getNodes(); |
Lines 419-440
Link Here
|
419 |
return arr == null ? null : arr.nodes (); |
430 |
return arr == null ? null : arr.nodes (); |
420 |
} |
431 |
} |
421 |
|
432 |
|
422 |
/** Getter for list of nodes. Called from getNodes (). |
433 |
private static final Object LOCK = new Object (); |
423 |
* @return list of nodes associated with this object |
|
|
424 |
*/ |
425 |
final Node[] computeNodes () { |
426 |
return getArray ().nodes (); |
427 |
} |
428 |
|
429 |
/** Obtains references to array holder. If it does not exist, it is |
434 |
/** Obtains references to array holder. If it does not exist, it is |
430 |
* created. |
435 |
* created. |
|
|
436 |
* |
437 |
* @param cannotWorkBetter array of size 1 or null, will contain true, if |
438 |
* the getArray cannot be initialized (we are underread access |
439 |
* and nother thread is responbile for initialization, in such case |
440 |
* give up on computation of best result |
431 |
*/ |
441 |
*/ |
432 |
private ChildrenArray getArray () { |
442 |
private ChildrenArray getArray (boolean[] cannotWorkBetter) { |
433 |
ChildrenArray arr = (ChildrenArray)array.get (); |
443 |
ChildrenArray arr; |
434 |
if (arr == null) { |
444 |
boolean doInitialize = false; |
435 |
// create new array |
445 |
synchronized (LOCK) { |
436 |
arr = ChildrenArray.create (this); |
446 |
arr = (ChildrenArray)array.get (); |
|
|
447 |
if (arr == null) { |
448 |
arr = new ChildrenArray (); |
449 |
// register the array with the children |
450 |
registerChildrenArray (arr, true); |
451 |
doInitialize = true; |
452 |
} |
453 |
} |
454 |
|
455 |
if (doInitialize) { |
456 |
// this call can cause a lot of callbacks => be prepared |
457 |
// to handle them as clean as possible |
458 |
this.callAddNotify (); |
459 |
|
460 |
synchronized (LOCK) { |
461 |
// now attach to children, so when children == null => we are |
462 |
// not fully initialized!!!! |
463 |
arr.children = this; |
464 |
LOCK.notifyAll (); |
465 |
} |
466 |
} else { |
467 |
// otherwise, if not initialize yet (arr.children) wait |
468 |
// for the initialization to finish, but only if we can wait |
469 |
|
470 |
// we are not in ReadAccess |
471 |
// Children.MUTEX.isReadAccess, if such call would be added to Mutex |
472 |
class MutexChecker implements Runnable { |
473 |
public boolean inReadAccess = true; |
474 |
public void run () { |
475 |
inReadAccess = false; |
476 |
} |
477 |
} |
478 |
MutexChecker test = new MutexChecker(); |
479 |
// the code will run either immediatally or after we leave readAccess |
480 |
// section |
481 |
Children.MUTEX.postWriteRequest(test); |
482 |
|
483 |
if (test.inReadAccess) { |
484 |
// fail, we are in read access |
485 |
if (cannotWorkBetter != null) { |
486 |
cannotWorkBetter[0] = true; |
487 |
} |
488 |
return arr; |
489 |
} |
490 |
|
491 |
// otherwise we can wait |
492 |
synchronized (LOCK) { |
493 |
while (arr.children == null) { |
494 |
try { |
495 |
LOCK.wait (); |
496 |
} catch (InterruptedException ex) { |
497 |
} |
498 |
} |
499 |
} |
437 |
} |
500 |
} |
|
|
501 |
|
438 |
return arr; |
502 |
return arr; |
439 |
} |
503 |
} |
440 |
|
504 |
|
Lines 1000-1013
Link Here
|
1000 |
|
1064 |
|
1001 |
public Collection nodes () { |
1065 |
public Collection nodes () { |
1002 |
// forces creation of the array |
1066 |
// forces creation of the array |
1003 |
ChildrenArray arr = getArray (); |
1067 |
ChildrenArray arr = getArray (null); |
1004 |
|
1068 |
|
1005 |
return arr.nodesFor (this); |
1069 |
return arr.nodesFor (this); |
1006 |
} |
1070 |
} |
1007 |
|
1071 |
|
1008 |
public void useNodes (Collection nodes) { |
1072 |
public void useNodes (Collection nodes) { |
1009 |
// forces creation of the array |
1073 |
// forces creation of the array |
1010 |
ChildrenArray arr = getArray (); |
1074 |
ChildrenArray arr = getArray (null); |
1011 |
|
1075 |
|
1012 |
arr.useNodes (this, nodes); |
1076 |
arr.useNodes (this, nodes); |
1013 |
|
1077 |
|
Lines 1152-1158
Link Here
|
1152 |
final void refreshImpl () { |
1216 |
final void refreshImpl () { |
1153 |
if ( isInitialized() ) { |
1217 |
if ( isInitialized() ) { |
1154 |
Array.this.refreshEntry (getNodesEntry ()); |
1218 |
Array.this.refreshEntry (getNodesEntry ()); |
1155 |
super.computeNodes (); |
1219 |
super.getArray (null).nodes (); |
1156 |
} |
1220 |
} |
1157 |
else if ( nodes != null ) { |
1221 |
else if ( nodes != null ) { |
1158 |
for( Iterator it = nodes.iterator(); it.hasNext(); ) { |
1222 |
for( Iterator it = nodes.iterator(); it.hasNext(); ) { |