sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1393020 - in /sis/trunk/sis-utility/src: main/java/org/apache/sis/internal/util/ main/java/org/apache/sis/util/ test/java/org/apache/sis/internal/util/ test/java/org/apache/sis/test/suite/
Date Tue, 02 Oct 2012 16:38:01 GMT
Author: desruisseaux
Date: Tue Oct  2 16:38:01 2012
New Revision: 1393020

URL: http://svn.apache.org/viewvc?rev=1393020&view=rev
Log:
Base classes for managing the background threads to be created internally by the library.

Added:
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java   (with
props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
  (with props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java   (with
props)
    sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java   (with props)
    sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/
    sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
  (with props)
Modified:
    sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java?rev=1393020&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java Tue
Oct  2 16:38:01 2012
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+
+/**
+ * Base class for all daemon threads in the SIS library. This class provides a
+ * {@link #isKillRequested()} flag which shall be tested by the daemon threads.
+ * It is okay to test this flag only when catching {@link InterruptedException},
+ * as below:
+ *
+ * {@preformat java
+ *     while (someCondition) {
+ *         try {
+ *             someObject.wait();
+ *         } catch (InterruptedException e) {
+ *             if (isKillRequested()) {
+ *                 break; // Exit the loop for stopping the thread.
+ *             }
+ *         }
+ *     }
+ * }
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.09)
+ * @version 0.3
+ * @module
+ */
+public class DaemonThread extends Thread {
+    /**
+     * Set to {@code true} when the {@link #kill()} method has been invoked.
+     */
+    private volatile boolean killRequested;
+
+    /**
+     * Creates a new daemon thread. This constructor sets the daemon flag to {@code true}.
+     *
+     * @param group The thread group.
+     * @param name  The thread name.
+     */
+    protected DaemonThread(final ThreadGroup group, final String name) {
+        super(group, name);
+        setDaemon(true);
+    }
+
+    /**
+     * Returns {@code true} if {@link #kill()} has been invoked.
+     *
+     * @return {@code true} if {@link #kill()} has been invoked.
+     */
+    protected final boolean isKillRequested() {
+        return killRequested;
+    }
+
+    /**
+     * Kills all the given threads (ignoring null arguments),
+     * and waits for the threads to die before to return.
+     *
+     * @param  stopWaitingAt Value of {@link System#nanoTime()} when to stop waiting.
+     *         This is used for preventing the shutdown to block an indefinite amount of
time.
+     * @param  threads The threads to kill. Null arguments are silently ignored.
+     * @throws InterruptedException If an other thread invoked {@link #interrupt()} while
+     *         we were waiting for the daemon threads to die.
+     */
+    static void kill(final long stopWaitingAt, final DaemonThread... threads)
+            throws InterruptedException
+    {
+        for (final DaemonThread thread : threads) {
+            if (thread != null) {
+                thread.killRequested = true;
+                thread.interrupt();
+            }
+        }
+        for (final DaemonThread thread : threads) {
+            if (thread != null) {
+                final long delay = stopWaitingAt - System.nanoTime();
+                if (delay <= 0) break;
+                thread.join(delay);
+            }
+        }
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/DaemonThread.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java?rev=1393020&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
(added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
Tue Oct  2 16:38:01 2012
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+
+import org.apache.sis.util.Disposable;
+import org.apache.sis.util.logging.Logging;
+
+
+/**
+ * A thread processing all {@link Reference} instances enqueued in a {@link ReferenceQueue}.
+ * This is the central place where <em>every</em> weak references produced by
the SIS library
+ * are consumed. This thread will invoke the {@link Disposeable#dispose()} method for each
+ * references enqueued by the garbage collector. Those references <strong>must</strong>
+ * implement the {@link Disposable} interface.
+ * <p>
+ * Example:
+ *
+ * {@preformat java
+ *     final class MyReference extends WeakReference<MyType> implements Disposable
{
+ *         MyReference(MyType referent) {
+ *             super(referent, ReferenceQueueConsumer.DEFAULT.queue);
+ *             assert ReferenceQueueConsumer.DEFAULT.isAlive();
+ *         }
+ *
+ *         @Override
+ *         public void dispose() {
+ *             // Perform here some cleaning work that must be done when the referent has
+ *             // been garbage-collected. Remember that get() returns null from this point.
+ *         }
+ *     }
+ * }
+ *
+ * @param <T> The type of objects being referenced.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.00)
+ * @version 0.3
+ * @module
+ */
+public final class ReferenceQueueConsumer<T> extends DaemonThread {
+    /**
+     * The default thread.
+     */
+    public static final ReferenceQueueConsumer<Object> DEFAULT;
+    static {
+        // Call to Thread.start() must be outside the constructor
+        // (Reference: Goetz et al.: "Java Concurrency in Practice").
+        DEFAULT = new ReferenceQueueConsumer<Object>("ReferenceQueueConsumer");
+        DEFAULT.start();
+    }
+
+    /**
+     * List of references collected by the garbage collector. This reference shall be given
to
+     * {@link Reference} constructors as documented in the class javadoc. Those {@code Reference}
+     * sub-classes <strong>must</strong> implement the {@link Disposable} interface.
+     */
+    public final ReferenceQueue<T> queue = new ReferenceQueue<T>();
+
+    /**
+     * Constructs a new thread as a daemon thread. This thread will be sleeping most of the
time.
+     * It will run only only a few nanoseconds every time a new {@link Reference} is enqueded.
+     *
+     * @param name The thread name. This name appears in the debugger.
+     */
+    private ReferenceQueueConsumer(final String name) {
+        super(Threads.RESOURCE_DISPOSERS, name);
+        setPriority(Thread.MAX_PRIORITY);
+        // The above line sets the priority to the maximal value allowed by the
+        // RESOURCE_DISPOSERS group, which is actually lower than MAX_PRIORITY.
+    }
+
+    /**
+     * Loop to be run during the virtual machine lifetime.
+     */
+    @Override
+    public final void run() {
+        /*
+         * The reference queue should never be null. However some strange cases have been
+         * observed at shutdown time. If the field become null, assume that a shutdown is
+         * under way and let the thread terminate.
+         */
+        ReferenceQueue<T> queue;
+        while ((queue = this.queue) != null) {
+            try {
+                /*
+                 * Block until a reference is enqueued. The reference should never be null
+                 * when using the method without timeout (it could be null if we specified
+                 * a timeout). If the remove() method behaves as if a timeout occurred, we
+                 * may be in the middle of a shutdown. Continue anyway as long as we didn't
+                 * received the kill event.
+                 */
+                final Reference<? extends T> ref = queue.remove();
+                if (ref != null) {
+                    /*
+                     * If the reference does not implement the Disposeable interface, we
want
+                     * the ClassCastException to be logged in the "catch" block since it
would
+                     * be a programming error that we want to know about.
+                     */
+                    ((Disposable) ref).dispose();
+                    continue;
+                }
+            } catch (InterruptedException exception) {
+                // Probably the 'kill()' method has been invoked.
+                // We need to test 'isKillRequested()' below.
+            } catch (Throwable exception) {
+                Logging.unexpectedException(getClass(), "run", exception);
+            }
+            if (isKillRequested()) {
+                break;
+            }
+        }
+        // Do not log anything at this point, since the loggers may be shutdown now.
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/ReferenceQueueConsumer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java?rev=1393020&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java Tue Oct
 2 16:38:01 2012
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import org.apache.sis.util.logging.Logging;
+
+
+/**
+ * Utilities methods for threads. This class declares in a single place every {@link ThreadGroup}
+ * used in SIS. Their intend is to bring some order in debugger informations, by grouping
the
+ * threads created by SIS together under the same parent tree node.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.03)
+ * @version 0.3
+ * @module
+ */
+public final class Threads {
+    /**
+     * The parent of every threads declared in this class. This parent will be declared as
close
+     * as possible to the root of all thread groups (i.e. not as an application thread subgroup).
+     * The intend is to separate the library thread groups from the user application thread
groups.
+     */
+    private static final ThreadGroup SIS;
+    static {
+        ThreadGroup parent = Thread.currentThread().getThreadGroup();
+        try {
+            ThreadGroup candidate;
+            while ((candidate = parent.getParent()) != null) {
+                parent = candidate;
+            }
+        } catch (SecurityException e) {
+            // If we are not allowed to get the parent, stop there.
+            // We went up in the tree as much as we were allowed to.
+        }
+        SIS = new ThreadGroup(parent, "Apache SIS");
+    }
+
+    /**
+     * The group of threads for resources disposal. We give them a priority slightly higher
+     * than the normal one since this group shall contain only tasks to be completed very
+     * quickly, and the benefit of executing those tasks soon is more resources made available.
+     */
+    static final ThreadGroup RESOURCE_DISPOSERS = new ThreadGroup(SIS, "ResourceDisposers")
{
+        @Override public void uncaughtException(final Thread thread, final Throwable exception)
{
+            Logging.severeException(Logging.getLogger("org.apache.sis"), thread.getClass(),
"run", exception);
+        }
+    };
+    static {
+        RESOURCE_DISPOSERS.setMaxPriority(Thread.NORM_PRIORITY + 2);
+    }
+
+    /**
+     * Do not allows instantiation of this class.
+     */
+    private Threads() {
+    }
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/internal/util/Threads.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java?rev=1393020&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java (added)
+++ sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java Tue Oct  2 16:38:01
2012
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.util;
+
+
+/**
+ * A resource that can be disposed when waiting for the garbage collector would be overly
+ * conservative. Invoking the {@link #dispose()} method allows any resources held by this
+ * object to be released. The result of calling any other method subsequent to a call to
+ * this method is undefined.
+ *
+ * {@section Relationship with <code>Closeable</code>}
+ * Some SIS classes may implement both the {@code Disposeable} and {@link java.io.Closeable}
+ * interfaces. While very similar, those two interfaces serve slightly different purposes.
+ * The {@code Closeable} interface closes a stream or a connection, but some classes can
be
+ * reused with a different stream. For example an {@link javax.imageio.ImageReader} can be
+ * instantiated once and reused many time for reading different image streams of the same
+ * format. However once an object has been disposed, it can not be used anymore.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3 (derived from geotk-3.10)
+ * @version 0.3
+ * @module
+ *
+ * @see java.awt.Graphics#dispose()
+ * @see javax.imageio.ImageReader#dispose()
+ * @see javax.imageio.ImageWriter#dispose()
+ */
+public interface Disposable {
+    /**
+     * Allows any resources held by this object to be released. The result of calling any
other
+     * method (other than {@code finalize()}) subsequent to a call to this method is undefined.
+     */
+    void dispose();
+}

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/main/java/org/apache/sis/util/Disposable.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java?rev=1393020&view=auto
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
(added)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
Tue Oct  2 16:38:01 2012
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.util;
+
+import java.lang.ref.ReferenceQueue;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+
+/**
+ * Tests {@link ReferenceQueueConsumer}.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.3
+ * @version 0.3
+ * @module
+ */
+public final strictfp class ReferenceQueueConsumerTest extends TestCase {
+    /**
+     * Verifies that invoking {@link Thread#interrupt()} will cause {@link InterruptedException}
+     * to be thrown even if invoked <em>before</em> {@link ReferenceQueue#remove()}
put the
+     * thread in a waiting state. This behavior is documented in {@link Object#wait()}, but
+     * the reference queue javadoc is silent on this topic.
+     * <p>
+     * This method is not a test of the SIS library, but rather a verification of our JDK
+     * library interpretation.
+     *
+     * @throws InterruptedException This is the excepted exception.
+     */
+    @Test(expected=InterruptedException.class)
+    public void verifyInterruptAssumption() throws InterruptedException {
+        final ReferenceQueue<Object> queue = new ReferenceQueue<Object>();
+        Thread.currentThread().interrupt();
+        assertNull(queue.remove(1000));
+    }
+}

Propchange: sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/trunk/sis-utility/src/test/java/org/apache/sis/internal/util/ReferenceQueueConsumerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java
URL: http://svn.apache.org/viewvc/sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java?rev=1393020&r1=1393019&r2=1393020&view=diff
==============================================================================
--- sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java (original)
+++ sis/trunk/sis-utility/src/test/java/org/apache/sis/test/suite/UtilityTestSuite.java Tue
Oct  2 16:38:01 2012
@@ -43,7 +43,8 @@ import org.junit.runners.Suite;
   org.apache.sis.util.logging.PerformanceLevelTest.class,
   org.apache.sis.util.type.TypesTest.class,
   org.apache.sis.util.type.SimpleInternationalStringTest.class,
-  org.apache.sis.util.type.DefaultInternationalStringTest.class
+  org.apache.sis.util.type.DefaultInternationalStringTest.class,
+  org.apache.sis.internal.util.ReferenceQueueConsumerTest.class
 })
 public final strictfp class UtilityTestSuite extends TestSuite {
 }



Mime
View raw message