diff options
Diffstat (limited to 'src/java/com/jogamp/common/util/InterruptSource.java')
-rw-r--r-- | src/java/com/jogamp/common/util/InterruptSource.java | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/java/com/jogamp/common/util/InterruptSource.java b/src/java/com/jogamp/common/util/InterruptSource.java new file mode 100644 index 0000000..01fcdb5 --- /dev/null +++ b/src/java/com/jogamp/common/util/InterruptSource.java @@ -0,0 +1,157 @@ +/** + * Copyright 2015 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.common.util; + +/** + * Interface exposing {@link java.lang.Thread#interrupt()} source, + * intended for {@link java.lang.Thread} specializations. + * @since 2.3.2 + */ +public interface InterruptSource { + /** + * Returns the source of the last {@link #interrupt()} call. + * @param clear if true, issues {@link #clearInterruptSource()} + */ + Throwable getInterruptSource(final boolean clear); + + /** + * Returns the count of {@link java.lang.Thread#interrupt()} calls. + * @param clear if true, issues {@link #clearInterruptSource()} + */ + int getInterruptCounter(final boolean clear); + + /** + * Clears source and count of {@link java.lang.Thread#interrupt()} calls, if any. + */ + void clearInterruptSource(); + + public static class Util { + /** + * Casts given {@link java.lang.Thread} to {@link InterruptSource} + * if applicable, otherwise returns {@code null}. + */ + public static InterruptSource get(final java.lang.Thread t) { + if(t instanceof InterruptSource) { + return (InterruptSource)t; + } else { + return null; + } + } + /** + * Casts current {@link java.lang.Thread} to {@link InterruptSource} + * if applicable, otherwise returns {@code null}. + */ + public static InterruptSource currentThread() { + return get(java.lang.Thread.currentThread()); + } + } + + /** + * {@link java.lang.Thread} specialization implementing {@link InterruptSource} + * to track {@link java.lang.Thread#interrupt()} calls. + * @since 2.3.2 + */ + public static class Thread extends java.lang.Thread implements InterruptSource { + volatile Throwable interruptSource = null; + volatile int interruptCounter = 0; + final Object sync = new Object(); + + /** + * See {@link Thread#Thread(} for details. + */ + public Thread() { + super(); + } + /** + * See {@link Thread#Thread(ThreadGroup, Runnable)} for details. + * @param tg explicit {@link ThreadGroup}, may be {@code null} + * @param target explicit {@link Runnable}, may be {@code null} + */ + public Thread(final ThreadGroup tg, final Runnable target) { + super(tg, target); + } + /** + * See {@link Thread#Thread(ThreadGroup, Runnable, String)} for details. + * @param tg explicit {@link ThreadGroup}, may be {@code null} + * @param target explicit {@link Runnable}, may be {@code null} + * @param name explicit name of thread, must not be {@code null} + */ + public Thread(final ThreadGroup tg, final Runnable target, final String name) { + super(tg, target, name); + } + + /** + * Depending on whether {@code name} is null, either + * {@link #Thread(ThreadGroup, Runnable, String)} or + * {@link #Thread(ThreadGroup, Runnable)} is being utilized. + * @param tg explicit {@link ThreadGroup}, may be {@code null} + * @param target explicit {@link Runnable}, may be {@code null} + * @param name explicit name of thread, may be {@code null} + */ + public static Thread create(final ThreadGroup tg, final Runnable target, final String name) { + return null != name ? new Thread(tg, target, name) : new Thread(tg, target); + } + + @Override + public final Throwable getInterruptSource(final boolean clear) { + synchronized(sync) { + final Throwable r = interruptSource; + if( clear ) { + clearInterruptSource(); + } + return r; + } + } + @Override + public final int getInterruptCounter(final boolean clear) { + synchronized(sync) { + final int r = interruptCounter; + if( clear ) { + clearInterruptSource(); + } + return r; + } + } + @Override + public final void clearInterruptSource() { + synchronized(sync) { + interruptCounter = 0; + interruptSource = null; + } + } + @Override + public final void interrupt() { + synchronized(sync) { + interruptCounter++; + interruptSource = new Throwable(getName()+".interrupt() #"+interruptCounter); + } + super.interrupt(); + } + } +} |