summaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/common
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-02-13 13:04:27 +0100
committerSven Gothel <[email protected]>2013-02-13 13:04:27 +0100
commitb387d012103a02eb7d5eb919306583295ef09a38 (patch)
tree2e01b804cc071e0350ec72059cbd470d23c596e0 /src/java/com/jogamp/common
parent30841742e735e70b3946d16711089960084e894c (diff)
Adding Function and FunctionTask extending RunnableTask functionality
Function allows passing arguments and having a return value in contrast to Runnable, where FunctionTask allows a Function to be invoked and waited for.
Diffstat (limited to 'src/java/com/jogamp/common')
-rw-r--r--src/java/com/jogamp/common/util/Function.java49
-rw-r--r--src/java/com/jogamp/common/util/FunctionTask.java160
-rw-r--r--src/java/com/jogamp/common/util/RunnableTask.java151
-rw-r--r--src/java/com/jogamp/common/util/TaskBase.java137
4 files changed, 379 insertions, 118 deletions
diff --git a/src/java/com/jogamp/common/util/Function.java b/src/java/com/jogamp/common/util/Function.java
new file mode 100644
index 0000000..8bec99c
--- /dev/null
+++ b/src/java/com/jogamp/common/util/Function.java
@@ -0,0 +1,49 @@
+/**
+ * Copyright 2013 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;
+
+/**
+ * Generic function interface to perform an action w/ given optional arguments
+ * producing an optional result.
+ * <p>
+ * For <code>void</code> functions, simply use type <code>Object</code>
+ * and ignore the result and/or arguments.
+ * </p>
+ *
+ * @param <T> the result type of {@link #eval(Object...)}
+ */
+public interface Function<R,A> {
+ /**
+ * Implementation may compute variable <code>args</code> list
+ * and returns a result.
+ *
+ * @param args variable argument list, <code>A[]</code>, maybe null
+ * @return the result.
+ */
+ R eval(A... args);
+}
diff --git a/src/java/com/jogamp/common/util/FunctionTask.java b/src/java/com/jogamp/common/util/FunctionTask.java
new file mode 100644
index 0000000..8a1ef44
--- /dev/null
+++ b/src/java/com/jogamp/common/util/FunctionTask.java
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2013 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;
+
+/**
+ * Helper class to provide a Runnable queue implementation with a Runnable wrapper
+ * which notifies after execution for the <code>invokeAndWait()</code> semantics.
+ */
+public class FunctionTask<R,A> extends TaskBase implements Function<R,A> {
+ protected Function<R,A> runnable;
+ protected R result;
+ protected A[] args;
+
+ /**
+ * Invokes <code>func</code>.
+ * @param waitUntilDone if <code>true</code>, waits until <code>func</code> execution is completed, otherwise returns immediately.
+ * @param func the {@link Function} to execute.
+ * @param args the {@link Function} arguments
+ * @return the {@link Function} return value
+ */
+ public static <U,V> U invoke(boolean waitUntilDone, Function<U,V> func, V... args) {
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final FunctionTask<U,V> rt = new FunctionTask<U,V>( func, waitUntilDone ? sync : null, true );
+ final U res;
+ synchronized(sync) {
+ res = rt.eval(args);
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
+ return res;
+ }
+
+ /**
+ * 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 until <code>runnable</code> execution is completed,
+ * or <code>null</code> if waiting is not desired.
+ * @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 FunctionTask(Function<R,A> runnable, Object syncObject, boolean catchExceptions) {
+ super(syncObject, catchExceptions);
+ this.runnable = runnable ;
+ result = null;
+ args = null;
+ }
+
+ /** Return the user action */
+ public Function<R,A> getRunnable() {
+ return runnable;
+ }
+
+ /**
+ * Sets the arguments for {@link #run()}.
+ * They will be cleared afterwards.
+ */
+ public void setArgs(A... args) {
+ this.args = args;
+ }
+
+ /**
+ * Retrieves the cached result of {@link #run()}
+ * and clears it afterwards.
+ */
+ public R getResult() {
+ final R res = result;
+ result = null;
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Calls {@link #eval(Object...)}.
+ * </p>
+ * <p>
+ * You may set the {@link #eval(Object...)} arguments via {@link #setArgs(Object...)}
+ * and retrieve the result via {@link #getResult()}.
+ * </p>
+ */
+ @Override
+ public void run() {
+ result = eval(args);
+ args = null;
+ }
+
+ @Override
+ public R eval(A... args) {
+ R res = null;
+ tStarted = System.currentTimeMillis();
+ if(null == syncObject) {
+ try {
+ res = runnable.eval(args);
+ } catch (Throwable t) {
+ runnableException = t;
+ if(!catchExceptions) {
+ throw new RuntimeException(runnableException);
+ }
+ } finally {
+ tExecuted = System.currentTimeMillis();
+ }
+ } else {
+ synchronized (syncObject) {
+ try {
+ res = runnable.eval(args);
+ } catch (Throwable t) {
+ runnableException = t;
+ if(!catchExceptions) {
+ throw new RuntimeException(runnableException);
+ }
+ } finally {
+ tExecuted = System.currentTimeMillis();
+ syncObject.notifyAll();
+ }
+ }
+ }
+ return res;
+ }
+}
+
diff --git a/src/java/com/jogamp/common/util/RunnableTask.java b/src/java/com/jogamp/common/util/RunnableTask.java
index b0ce159..6a4ccb3 100644
--- a/src/java/com/jogamp/common/util/RunnableTask.java
+++ b/src/java/com/jogamp/common/util/RunnableTask.java
@@ -32,55 +32,49 @@ package com.jogamp.common.util;
* Helper class to provide a Runnable queue implementation with a Runnable wrapper
* which notifies after execution for the <code>invokeAndWait()</code> semantics.
*/
-public class RunnableTask implements Runnable {
- Runnable runnable;
- final Object syncObject;
- boolean catchExceptions;
- Object attachment;
-
- Throwable runnableException;
- long tCreated, tStarted;
- volatile long tExecuted;
- volatile boolean isFlushed;
-
- /**
- * 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 class RunnableTask extends TaskBase {
+ protected final Runnable runnable;
/**
- * 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>
+ * Invoks <code>runnable</code>.
+ * @param waitUntilDone if <code>true</code>, waits until <code>runnable</code> execution is completed, otherwise returns immediately.
+ * @param runnable the {@link Runnable} to execute.
*/
- public RunnableTask(Runnable runnable, Object syncObject) {
- this(runnable, syncObject, false);
+ public static void invoke(boolean waitUntilDone, Runnable runnable) {
+ Throwable throwable = null;
+ final Object sync = new Object();
+ final RunnableTask rt = new RunnableTask( runnable, waitUntilDone ? sync : null, true );
+ synchronized(sync) {
+ rt.run();
+ if( waitUntilDone ) {
+ try {
+ sync.wait();
+ } catch (InterruptedException ie) {
+ throwable = ie;
+ }
+ if(null==throwable) {
+ throwable = rt.getThrowable();
+ }
+ if(null!=throwable) {
+ throw new RuntimeException(throwable);
+ }
+ }
+ }
}
-
+
/**
* Create a RunnableTask object w/ synchronization,
- * ie. suitable for <code>invokeAndWait()</code>.
+ * ie. suitable for <code>invokeAndWait()</code>, i.e. {@link #invoke(boolean, Runnable) invoke(true, runnable)}.
*
* @param runnable the user action
- * @param syncObject the synchronization object the caller shall wait for in case of <code>invokeAndWai()t</code>
+ * @param syncObject the synchronization object if caller wait until <code>runnable</code> execution is completed,
+ * or <code>null</code> if waiting is not desired.
* @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) {
+ super(syncObject, catchExceptions);
this.runnable = runnable ;
- this.syncObject = syncObject ;
- this.catchExceptions = catchExceptions ;
- tCreated = System.currentTimeMillis();
- tStarted = 0;
- tExecuted = 0;
- isFlushed = false;
}
/** Return the user action */
@@ -88,30 +82,7 @@ public class RunnableTask implements Runnable {
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.
- */
- public void setAttachment(Object o) {
- attachment = o;
- }
-
- /**
- * Return the attachment object if any.
- * @see #setAttachment(Object)
- */
- public Object getAttachment() {
- return attachment;
- }
-
+ @Override
public void run() {
tStarted = System.currentTimeMillis();
if(null == syncObject) {
@@ -139,63 +110,7 @@ public class RunnableTask implements Runnable {
syncObject.notifyAll();
}
}
- }
- }
-
- /**
- * Simply flush this task and notify a waiting executor.
- * The executor which might have been blocked until notified
- * will be unblocked and the task removed from the queue.
- *
- * @see #isFlushed()
- * @see #isInQueue()
- */
- public void flush() {
- if(!isExecuted() && hasWaiter()) {
- synchronized (syncObject) {
- isFlushed = true;
- syncObject.notifyAll();
- }
- }
- }
-
- /**
- * @return !{@link #isExecuted()} && !{@link #isFlushed()}
- */
- public boolean isInQueue() { return 0 != tExecuted && !isFlushed; }
-
- /**
- * @return True if executed, otherwise false;
- */
- public boolean isExecuted() { return 0 != tExecuted ; }
-
- /**
- * @return True if flushed, otherwise false;
- */
- public boolean isFlushed() { return isFlushed; }
-
- /**
- * @return True if invoking thread waits until done,
- * ie a <code>notifyObject</code> was passed, otherwise false;
- */
- public boolean hasWaiter() { return null != syncObject; }
-
- /**
- * @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; }
-
- public long getTimestampCreate() { return tCreated; }
- public long getTimestampBeforeExec() { return tStarted; }
- public long getTimestampAfterExec() { return tExecuted; }
- public long getDurationInQueue() { return tStarted - tCreated; }
- public long getDurationInExec() { return tExecuted - tStarted; }
- public long getDurationTotal() { return tExecuted - tCreated; }
-
- @Override
- public String toString() {
- return "RunnableTask[executed "+isExecuted()+", t2-t0 "+getDurationTotal()+", t2-t1 "+getDurationInExec()+", t1-t0 "+getDurationInQueue()+", throwable "+getThrowable()+", Runnable "+runnable+", Attachment "+attachment+"]";
- }
+ }
+ }
}
diff --git a/src/java/com/jogamp/common/util/TaskBase.java b/src/java/com/jogamp/common/util/TaskBase.java
new file mode 100644
index 0000000..e9366c2
--- /dev/null
+++ b/src/java/com/jogamp/common/util/TaskBase.java
@@ -0,0 +1,137 @@
+/**
+ * Copyright 2010 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;
+
+/**
+ * Helper class to provide a Runnable queue implementation with a Runnable wrapper
+ * which notifies after execution for the <code>invokeAndWait()</code> semantics.
+ */
+public abstract class TaskBase implements Runnable {
+ protected final Object syncObject;
+ protected final boolean catchExceptions;
+
+ protected Object attachment;
+ protected Throwable runnableException;
+ protected long tCreated, tStarted;
+ protected volatile long tExecuted;
+ protected volatile boolean isFlushed;
+
+ protected TaskBase(Object syncObject, boolean catchExceptions) {
+ this.syncObject = syncObject ;
+ this.catchExceptions = catchExceptions ;
+ tCreated = System.currentTimeMillis();
+ tStarted = 0;
+ tExecuted = 0;
+ isFlushed = false;
+ }
+
+ /**
+ * 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.
+ */
+ public void setAttachment(Object o) {
+ attachment = o;
+ }
+
+ /**
+ * Return the attachment object if any.
+ * @see #setAttachment(Object)
+ */
+ public Object getAttachment() {
+ return attachment;
+ }
+
+ @Override
+ public abstract void run();
+
+ /**
+ * Simply flush this task and notify a waiting executor.
+ * The executor which might have been blocked until notified
+ * will be unblocked and the task removed from the queue.
+ *
+ * @see #isFlushed()
+ * @see #isInQueue()
+ */
+ public void flush() {
+ if(!isExecuted() && hasWaiter()) {
+ synchronized (syncObject) {
+ isFlushed = true;
+ syncObject.notifyAll();
+ }
+ }
+ }
+
+ /**
+ * @return !{@link #isExecuted()} && !{@link #isFlushed()}
+ */
+ public boolean isInQueue() { return 0 != tExecuted && !isFlushed; }
+
+ /**
+ * @return True if executed, otherwise false;
+ */
+ public boolean isExecuted() { return 0 != tExecuted ; }
+
+ /**
+ * @return True if flushed, otherwise false;
+ */
+ public boolean isFlushed() { return isFlushed; }
+
+ /**
+ * @return True if invoking thread waits until done,
+ * ie a <code>notifyObject</code> was passed, otherwise false;
+ */
+ public boolean hasWaiter() { return null != syncObject; }
+
+ /**
+ * @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; }
+
+ public long getTimestampCreate() { return tCreated; }
+ public long getTimestampBeforeExec() { return tStarted; }
+ public long getTimestampAfterExec() { return tExecuted; }
+ public long getDurationInQueue() { return tStarted - tCreated; }
+ public long getDurationInExec() { return tExecuted - tStarted; }
+ public long getDurationTotal() { return tExecuted - tCreated; }
+
+ @Override
+ public String toString() {
+ return "RunnableTask[executed "+isExecuted()+", t2-t0 "+getDurationTotal()+", t2-t1 "+getDurationInExec()+", t1-t0 "+getDurationInQueue()+", throwable "+getThrowable()+", Attachment "+attachment+"]";
+ }
+}
+