aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-11-22 12:23:07 +0100
committerSven Gothel <[email protected]>2011-11-22 12:23:07 +0100
commit43b7675259eb76c570b6cc3a44fec2b9f6410697 (patch)
treecc6529445c1d750d7d54388277cff13dedbf1c42 /src
parent9f14ad29bf2d652c11328479ccb11030408c0543 (diff)
RunnableTask: Add documentation, incl. unit test. Add ReflectionUtil.MethodAccess, a convenient Method instance accessor.
Diffstat (limited to 'src')
-rw-r--r--src/java/com/jogamp/common/util/ReflectionUtil.java28
-rw-r--r--src/java/com/jogamp/common/util/RunnableTask.java56
-rw-r--r--src/junit/com/jogamp/common/util/TestRunnableTask01.java100
3 files changed, 174 insertions, 10 deletions
diff --git a/src/java/com/jogamp/common/util/ReflectionUtil.java b/src/java/com/jogamp/common/util/ReflectionUtil.java
index 6345efa..c771544 100644
--- a/src/java/com/jogamp/common/util/ReflectionUtil.java
+++ b/src/java/com/jogamp/common/util/ReflectionUtil.java
@@ -331,5 +331,33 @@ public final class ReflectionUtil {
return callMethod(null, getMethod(clazzName, methodName, argTypes, cl), args);
}
+ /** Convenient Method access class */
+ public static class MethodAccessor {
+ Method m = null;
+
+ /** Check {@link #available()} before using instance. */
+ public MethodAccessor(Class<?> clazz, String methodName, Class<?> ... argTypes) {
+ try {
+ m = ReflectionUtil.getMethod(clazz, methodName, argTypes);
+ } catch (JogampRuntimeException jre) { /* method n/a */ }
+ }
+
+ /** Returns true if method is available, otherwise false. */
+ public boolean available() {
+ return null != m;
+ }
+
+ /**
+ * Check {@link #available()} before calling to avoid throwing a JogampRuntimeException.
+ * @throws JogampRuntimeException if method is not available
+ */
+ public Object callMethod(Object instance, Object ... args) {
+ if(null == m) {
+ throw new JogampRuntimeException("Method not available. Instance: "+instance);
+ }
+ return ReflectionUtil.callMethod(instance, m, args);
+ }
+ }
+
}
diff --git a/src/java/com/jogamp/common/util/RunnableTask.java b/src/java/com/jogamp/common/util/RunnableTask.java
index 5ae102f..880bd64 100644
--- a/src/java/com/jogamp/common/util/RunnableTask.java
+++ b/src/java/com/jogamp/common/util/RunnableTask.java
@@ -34,35 +34,66 @@ package com.jogamp.common.util;
*/
public class RunnableTask implements Runnable {
Runnable runnable;
- final Object notifyObject;
+ final Object syncObject;
boolean catchExceptions;
Object attachment;
Throwable runnableException;
long ts0, ts1, ts2;
+ /**
+ * Create a RunnableTask object w/o synchronization,
+ * ie. not suitable for <code>invokeAndWait()</code>.
+ *
+ * @param runnable the user action
+ */
public RunnableTask(Runnable runnable) {
this(runnable, null, false);
}
- public RunnableTask(Runnable runnable, Object notifyObject) {
- this(runnable, notifyObject, false);
+ /**
+ * Create a RunnableTask object w/ synchronization,
+ * ie. suitable for <code>invokeAndWait()</code>.
+ *
+ * @param runnable the user action
+ * @param syncObject the synchronization object the caller shall wait for in case of <code>invokeAndWait()</code>
+ */
+ public RunnableTask(Runnable runnable, Object syncObject) {
+ this(runnable, syncObject, false);
}
- public RunnableTask(Runnable runnable, Object notifyObject, boolean catchExceptions) {
+ /**
+ * Create a RunnableTask object w/ synchronization,
+ * ie. suitable for <code>invokeAndWait()</code>.
+ *
+ * @param runnable the user action
+ * @param syncObject the synchronization object the caller shall wait for in case of <code>invokeAndWai()t</code>
+ * @param catchExceptions if true, exception during <code>runnable</code> execution are catched, otherwise not.
+ * Use {@link #getThrowable()} to determine whether an exception has been catched.
+ */
+ public RunnableTask(Runnable runnable, Object syncObject, boolean catchExceptions) {
this.runnable = runnable ;
- this.notifyObject = notifyObject ;
+ this.syncObject = syncObject ;
this.catchExceptions = catchExceptions ;
ts0 = System.currentTimeMillis();
ts1 = 0;
ts2 = 0;
}
+ /** Return the user action */
public Runnable getRunnable() {
return runnable;
}
/**
+ * Return the synchronization object if any.
+ * @see #RunnableTask(Runnable, Object, boolean)
+ */
+ public Object getSyncObject() {
+ return syncObject;
+ }
+
+ /**
* Attach a custom object to this task.
* Useful to piggybag further information, ie tag a task final.
*/
@@ -70,13 +101,17 @@ public class RunnableTask implements Runnable {
attachment = o;
}
+ /**
+ * Return the attachment object if any.
+ * @see #setAttachment(Object)
+ */
public Object getAttachment() {
return attachment;
}
public void run() {
ts1 = System.currentTimeMillis();
- if(null == notifyObject) {
+ if(null == syncObject) {
try {
runnable.run();
} catch (Throwable t) {
@@ -88,7 +123,7 @@ public class RunnableTask implements Runnable {
ts2 = System.currentTimeMillis();
}
} else {
- synchronized (notifyObject) {
+ synchronized (syncObject) {
try {
runnable.run();
} catch (Throwable t) {
@@ -98,7 +133,7 @@ public class RunnableTask implements Runnable {
}
} finally {
ts2 = System.currentTimeMillis();
- notifyObject.notifyAll();
+ syncObject.notifyAll();
}
}
}
@@ -113,10 +148,11 @@ public class RunnableTask implements Runnable {
* @return True if invoking thread waits until done,
* ie a <code>notifyObject</code> was passed, otherwise false;
*/
- public boolean hasWaiter() { return null != notifyObject; }
+ public boolean hasWaiter() { return null != syncObject; }
/**
- * @return A Throwable thrown while execution if any
+ * @return A thrown exception while execution of the user action, if any and if catched
+ * @see #RunnableTask(Runnable, Object, boolean)
*/
public Throwable getThrowable() { return runnableException; }
diff --git a/src/junit/com/jogamp/common/util/TestRunnableTask01.java b/src/junit/com/jogamp/common/util/TestRunnableTask01.java
new file mode 100644
index 0000000..56beaa4
--- /dev/null
+++ b/src/junit/com/jogamp/common/util/TestRunnableTask01.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 2011 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;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+
+import org.junit.Test;
+
+public class TestRunnableTask01 {
+
+ @Test
+ public void testInvokeAndWait00() throws IOException, InterruptedException, InvocationTargetException {
+ final Object syncObject = new Object();
+ final boolean[] done = {false};
+ final Runnable clientAction = new Runnable() {
+ public void run() {
+ synchronized(syncObject) {
+ System.err.println("CA.1: "+syncObject);
+ done[ 0 ] = true;
+ System.err.println("CA.X");
+ syncObject.notifyAll();
+ }
+ }
+ };
+
+ System.err.println("BB.0: "+syncObject);
+ synchronized (syncObject) {
+ System.err.println("BB.1: "+syncObject);
+ new Thread(clientAction, Thread.currentThread().getName()+"-clientAction").start();
+ try {
+ System.err.println("BB.2");
+ syncObject.wait();
+ System.err.println("BB.3");
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ System.err.println("BB.X");
+ }
+ }
+
+ @Test
+ public void testInvokeAndWait01() throws IOException, InterruptedException, InvocationTargetException {
+ final boolean[] done = {false};
+ final Runnable clientAction = new Runnable() {
+ public void run() {
+ System.err.println("CA.1");
+ done[ 0 ] = true;
+ System.err.println("CA.X");
+ }
+ };
+
+ final RunnableTask rTask = new RunnableTask(clientAction, new Object(), false);
+ System.err.println("BB.0: "+rTask.getSyncObject());
+ synchronized (rTask.getSyncObject()) {
+ System.err.println("BB.1: "+rTask.getSyncObject());
+ new Thread(rTask, Thread.currentThread().getName()+"-clientAction").start();
+ try {
+ System.err.println("BB.2");
+ rTask.getSyncObject().wait();
+ System.err.println("BB.3");
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ System.err.println("BB.X");
+ }
+ }
+
+ public static void main(String args[]) throws IOException {
+ String tstname = TestRunnableTask01.class.getName();
+ org.junit.runner.JUnitCore.main(tstname);
+ }
+
+}