Simplifying code inside Utilities class by making ActiveQueue impl a separate class.
Making AbstractLookup less dependent on the other features of Utilities class.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/openide.util/src/org/netbeans/modules/openide/util/ActiveQueue.java Tue Apr 07 11:31:38 2009 +0200
1.3 @@ -0,0 +1,108 @@
1.4 +package org.netbeans.modules.openide.util;
1.5 +
1.6 +import java.lang.ref.Reference;
1.7 +import java.lang.ref.ReferenceQueue;
1.8 +import java.util.logging.Level;
1.9 +import java.util.logging.Logger;
1.10 +
1.11 +/**
1.12 + * Implementation of the active reference queue.
1.13 + */
1.14 +public final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
1.15 +
1.16 + private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
1.17 + private static ActiveQueue activeReferenceQueue;
1.18 +
1.19 + /** number of known outstanding references */
1.20 + private int count;
1.21 + private boolean deprecated;
1.22 +
1.23 + ActiveQueue(boolean deprecated) {
1.24 + super();
1.25 + this.deprecated = deprecated;
1.26 + }
1.27 +
1.28 + public static synchronized ReferenceQueue<Object> queue() {
1.29 + if (activeReferenceQueue == null) {
1.30 + activeReferenceQueue = new ActiveQueue(false);
1.31 + }
1.32 +
1.33 + activeReferenceQueue.ping();
1.34 +
1.35 + return activeReferenceQueue;
1.36 + }
1.37 +
1.38 + @Override
1.39 + public Reference<Object> poll() {
1.40 + throw new UnsupportedOperationException();
1.41 + }
1.42 +
1.43 + @Override
1.44 + public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
1.45 + throw new InterruptedException();
1.46 + }
1.47 +
1.48 + @Override
1.49 + public Reference<Object> remove() throws InterruptedException {
1.50 + throw new InterruptedException();
1.51 + }
1.52 +
1.53 + public void run() {
1.54 + while (true) {
1.55 + try {
1.56 + Reference<?> ref = super.remove(0);
1.57 + LOGGER.finer("dequeued reference");
1.58 + if (!(ref instanceof Runnable)) {
1.59 + LOGGER.warning("A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " + ref.getClass());
1.60 + continue;
1.61 + }
1.62 + if (deprecated) {
1.63 + LOGGER.warning("Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() + " use Utilities.activeReferenceQueue");
1.64 + }
1.65 + // do the cleanup
1.66 + try {
1.67 + ((Runnable) ref).run();
1.68 + } catch (ThreadDeath td) {
1.69 + throw td;
1.70 + } catch (Throwable t) {
1.71 + // Should not happen.
1.72 + // If it happens, it is a bug in client code, notify!
1.73 + LOGGER.log(Level.WARNING, null, t);
1.74 + } finally {
1.75 + // to allow GC
1.76 + ref = null;
1.77 + }
1.78 + } catch (InterruptedException ex) {
1.79 + // Can happen during VM shutdown, it seems. Ignore.
1.80 + continue;
1.81 + }
1.82 + synchronized (this) {
1.83 + assert count > 0;
1.84 + count--;
1.85 + if (count == 0) {
1.86 + // We have processed all we have to process (for now at least).
1.87 + // Could be restarted later if ping() called again.
1.88 + // This could also happen in case someone called queue() once and tried
1.89 + // to use it for several references; in that case run() might never be called on
1.90 + // the later ones to be collected. Can't really protect against that situation.
1.91 + // See issue #86625 for details.
1.92 + LOGGER.fine("stopping thread");
1.93 + break;
1.94 + }
1.95 + }
1.96 + }
1.97 + }
1.98 +
1.99 + synchronized void ping() {
1.100 + if (count == 0) {
1.101 + Thread t = new Thread(this, "Active Reference Queue Daemon");
1.102 + t.setPriority(Thread.MIN_PRIORITY);
1.103 + t.setDaemon(true);
1.104 + t.start();
1.105 + LOGGER.fine("starting thread");
1.106 + } else {
1.107 + LOGGER.finer("enqueuing reference");
1.108 + }
1.109 + count++;
1.110 + }
1.111 +}
2.1 --- a/openide.util/src/org/openide/util/Utilities.java Tue Apr 07 00:37:21 2009 +0400
2.2 +++ b/openide.util/src/org/openide/util/Utilities.java Tue Apr 07 11:31:38 2009 +0200
2.3 @@ -41,6 +41,7 @@
2.4
2.5 package org.openide.util;
2.6
2.7 +import org.netbeans.modules.openide.util.ActiveQueue;
2.8 import java.awt.BorderLayout;
2.9 import java.awt.Component;
2.10 import java.awt.Container;
2.11 @@ -211,8 +212,6 @@
2.12 /** A height of the Mac OS X's menu */
2.13 private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
2.14
2.15 - private static ActiveQueue activeReferenceQueue;
2.16 -
2.17 /** The operating system on which NetBeans runs*/
2.18 private static int operatingSystem = -1;
2.19 private static final String[] keywords = new String[] {
2.20 @@ -271,7 +270,7 @@
2.21 * class MyReference extends WeakReference<Thing> implements Runnable {
2.22 * private final OtherInfo dataToCleanUp;
2.23 * public MyReference(Thing ref, OtherInfo data) {
2.24 - * super(ref, Utilities.activeReferenceQueue());
2.25 + * super(ref, Utilities.queue());
2.26 * dataToCleanUp = data;
2.27 * }
2.28 * public void run() {
2.29 @@ -293,14 +292,8 @@
2.30 * Do not attempt to cache the return value.
2.31 * @since 3.11
2.32 */
2.33 - public static synchronized ReferenceQueue<Object> activeReferenceQueue() {
2.34 - if (activeReferenceQueue == null) {
2.35 - activeReferenceQueue = new ActiveQueue(false);
2.36 - }
2.37 -
2.38 - activeReferenceQueue.ping();
2.39 -
2.40 - return activeReferenceQueue;
2.41 + public static ReferenceQueue<Object> activeReferenceQueue() {
2.42 + return ActiveQueue.queue();
2.43 }
2.44
2.45 /** Get the operating system on which NetBeans is running.
2.46 @@ -3117,107 +3110,4 @@
2.47 return deps;
2.48 }
2.49 }
2.50 -
2.51 - /** Implementation of the active queue.
2.52 - */
2.53 - private static final class ActiveQueue extends ReferenceQueue<Object> implements Runnable {
2.54 -
2.55 - private static final Logger LOGGER = Logger.getLogger(ActiveQueue.class.getName().replace('$', '.'));
2.56 -
2.57 - /** number of known outstanding references */
2.58 - private int count;
2.59 - private boolean deprecated;
2.60 -
2.61 - public ActiveQueue(boolean deprecated) {
2.62 - this.deprecated = deprecated;
2.63 - }
2.64 -
2.65 - @Override
2.66 - public Reference<Object> poll() {
2.67 - throw new UnsupportedOperationException();
2.68 - }
2.69 -
2.70 - @Override
2.71 - public Reference<Object> remove(long timeout) throws IllegalArgumentException, InterruptedException {
2.72 - throw new InterruptedException();
2.73 - }
2.74 -
2.75 - @Override
2.76 - public Reference<Object> remove() throws InterruptedException {
2.77 - throw new InterruptedException();
2.78 - }
2.79 -
2.80 - public void run() {
2.81 - while (true) {
2.82 - try {
2.83 - Reference<?> ref = super.remove(0);
2.84 - LOGGER.finer("dequeued reference");
2.85 -
2.86 - if (!(ref instanceof Runnable)) {
2.87 - LOGGER.warning(
2.88 - "A reference not implementing runnable has been added to the Utilities.activeReferenceQueue(): " +
2.89 - ref.getClass() // NOI18N
2.90 - );
2.91 -
2.92 - continue;
2.93 - }
2.94 -
2.95 - if (deprecated) {
2.96 - LOGGER.warning(
2.97 - "Utilities.ACTIVE_REFERENCE_QUEUE has been deprecated for " + ref.getClass() +
2.98 - " use Utilities.activeReferenceQueue" // NOI18N
2.99 - );
2.100 - }
2.101 -
2.102 - // do the cleanup
2.103 - try {
2.104 - ((Runnable) ref).run();
2.105 - } catch (ThreadDeath td) {
2.106 - throw td;
2.107 - } catch (Throwable t) {
2.108 - // Should not happen.
2.109 - // If it happens, it is a bug in client code, notify!
2.110 - LOGGER.log(Level.WARNING, null, t);
2.111 - } finally {
2.112 - // to allow GC
2.113 - ref = null;
2.114 - }
2.115 - } catch (InterruptedException ex) {
2.116 - // Can happen during VM shutdown, it seems. Ignore.
2.117 - continue;
2.118 - }
2.119 -
2.120 - synchronized (this) {
2.121 - assert count > 0;
2.122 - count--;
2.123 - if (count == 0) {
2.124 - // We have processed all we have to process (for now at least).
2.125 - // Could be restarted later if ping() called again.
2.126 - // This could also happen in case someone called activeReferenceQueue() once and tried
2.127 - // to use it for several references; in that case run() might never be called on
2.128 - // the later ones to be collected. Can't really protect against that situation.
2.129 - // See issue #86625 for details.
2.130 - LOGGER.fine("stopping thread");
2.131 - break;
2.132 - }
2.133 - }
2.134 - }
2.135 - }
2.136 -
2.137 - synchronized void ping() {
2.138 - if (count == 0) {
2.139 - Thread t = new Thread(this, "Active Reference Queue Daemon"); // NOI18N
2.140 - t.setPriority(Thread.MIN_PRIORITY);
2.141 - t.setDaemon(true); // to not prevent exit of VM
2.142 - t.start();
2.143 - // Note that this will not be printed during IDE startup because
2.144 - // it happens before logging is even initialized.
2.145 - LOGGER.fine("starting thread");
2.146 - } else {
2.147 - LOGGER.finer("enqueuing reference");
2.148 - }
2.149 - count++;
2.150 - }
2.151 -
2.152 - }
2.153 }
3.1 --- a/openide.util/src/org/openide/util/lookup/AbstractLookup.java Tue Apr 07 00:37:21 2009 +0400
3.2 +++ b/openide.util/src/org/openide/util/lookup/AbstractLookup.java Tue Apr 07 11:31:38 2009 +0200
3.3 @@ -64,7 +64,7 @@
3.4 import java.util.TreeSet;
3.5
3.6 import java.util.concurrent.Executor;
3.7 -import org.openide.util.Utilities;
3.8 +import org.netbeans.modules.openide.util.ActiveQueue;
3.9
3.10
3.11 /** Implementation of the lookup from OpenAPIs that is based on the
3.12 @@ -687,7 +687,7 @@
3.13 }
3.14
3.15 private static ReferenceQueue<Object> activeQueue() {
3.16 - return Utilities.activeReferenceQueue();
3.17 + return ActiveQueue.queue();
3.18 }
3.19
3.20 /** Storage to keep the internal structure of Pairs and to answer