diff options
-rwxr-xr-x | make/gluegen-cpptasks-base.xml | 69 | ||||
-rwxr-xr-x | make/jogamp-env.xml | 65 | ||||
-rwxr-xr-x | make/scripts/make.gluegen.all.macosx-java7.sh | 2 | ||||
-rw-r--r-- | make/stub_includes/jni/macosx/jawt_md.h | 68 | ||||
-rw-r--r-- | make/stub_includes/jni/macosx/jni_md.h | 47 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/Function.java | 49 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/FunctionTask.java | 164 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/RunnableTask.java | 155 | ||||
-rw-r--r-- | src/java/com/jogamp/common/util/TaskBase.java | 137 |
9 files changed, 600 insertions, 156 deletions
diff --git a/make/gluegen-cpptasks-base.xml b/make/gluegen-cpptasks-base.xml index 723c7c2..fcb382a 100755 --- a/make/gluegen-cpptasks-base.xml +++ b/make/gluegen-cpptasks-base.xml @@ -6,11 +6,14 @@ - by other projects which use GlueGen to generate native code and - need to compile that native code. - - - Before importing this file, the property "gluegen.root" must be - - defined; this is the relative path from the current working + - Before importing this file, the properties "gluegen.root" must be defined; + - this is the relative path from the current working - directory (e.g., from which the parent project's build.xml is being - executed) to the top of the checked-out GlueGen workspace. - + - The property "gluegen.root.abs-path" must be defined as well; + - this is the absolute path of "gluegen.root", see above. + - - The gluegen.cpptasks.detect.os target sets the following - properties appropriately. They are only set to "true" if the OS/CPU - configuration is exactly as specified. @@ -184,8 +187,16 @@ <!-- NOTE: the values of the macos<arch> attributes will not be overridden if already set externally --> <property name="macosppc" value="false" /> - <property name="macosx32" value="true" /> <property name="macosx64" value="true" /> + <!-- No 32bit binaries on OSX since Java7 --> + <condition property="macosx32" value="false" else="true"> + <or> + <contains string="${ant.java.version}" substring="1.7" casesensitive="false" /> + <contains string="${ant.java.version}" substring="1.8" casesensitive="false" /> + <contains string="${ant.java.version}" substring="1.9" casesensitive="false" /> + <contains string="${ant.java.version}" substring="2.0" casesensitive="false" /> + </or> + </condition> <!-- Need a way to be able to disable the macosx64 property specification in a build.xml --> <condition property="use.macosppc"> @@ -841,16 +852,29 @@ <!-- - Set up java.home.dir appropriately on all platforms. --> - <target name="setup.java.home.dir.nonmacosx" unless="isOSX"> + <target name="setup.java.home.dir.nonmacosx" unless="isOSX"> <!-- java home dir is up one directory as java.home points to '<java-install-dir>/jre' --> <property name="java.home.dir" value="${java.home}/.." /> - </target> - <target name="setup.java.home.dir.macosx" if="isOSX"> + <property name="java.includes.dir" value="${java.home.dir}/include" /> + </target> + <target name="setup.java.home.dir.macosx" if="isOSX"> + <!-- Java7 std location --> + <condition property="java.home.dir" + value="${java.home}/.."> + <available file="${java.home}/../include/jni.h"/> + </condition> + <condition property="java.includes.dir" + value="${java.home}/../include"> + <available file="${java.home}/../include/jni.h"/> + </condition> + <!-- Fallback value Java6 --> <property name="java.home.dir" value="/System/Library/Frameworks/JavaVM.framework/Home" /> - </target> - <target name="setup.java.home.dir" depends="setup.java.home.dir.nonmacosx,setup.java.home.dir.macosx"> - <property name="java.includes.dir" value="${java.home.dir}/include" /> - </target> + <property name="java.includes.dir" value="/System/Library/Frameworks/JavaVM.framework/Headers" /> + </target> + <target name="setup.java.home.dir" depends="setup.java.home.dir.nonmacosx,setup.java.home.dir.macosx"> + <echo message="java.home.dir ${java.home.dir}" /> + <echo message="java.includes.dir ${java.includes.dir}" /> + </target> <target name="gluegen.cpptasks.configure.compiler" depends="setup.java.home.dir"> @@ -1414,18 +1438,25 @@ <echo message="MacOSX" /> <property name="compiler.cfg.id.base" value="compiler.cfg.macosx" /> <property name="linker.cfg.id.base" value="linker.cfg.macosx" /> - <!-- Need to select either Java 10.6 Update 4's location or the old one --> + <!-- Java7 std location --> + <!-- Temporary workaround: + Provided darwin/jawt_md.h from Oracle for OSX / Java7 + has X11 dependencies and does not define JAWT_SurfaceLayers. + value="${java.includes.dir}/darwin"> + --> <condition property="java.includes.dir.platform" - value="/System/Library/Frameworks/JavaVM.framework/Headers" - else="/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Headers"> - <available file="/System/Library/Frameworks/JavaVM.framework/Headers/jni.h"/> + value="${gluegen.root.abs-path}/make/stub_includes/jni/macosx"> + <available file="${java.includes.dir}/darwin/jawt_md.h"/> </condition> - <condition property="java.osx.frameworks.dir" - value="/System/Library/Frameworks/JavaVM.framework/Frameworks" - else="/OSX/JavaVM.framework/Frameworks/does/not/exist"> - <available file="/System/Library/Frameworks/JavaVM.framework/Frameworks/JavaNativeFoundation.framework/Headers/JavaNativeFoundation.h"/> + <condition property="java.lib.dir.platform" + value="${java.home.dir}/jre/lib"> + <available file="${java.home.dir}/jre/lib/libjawt.dylib"/> </condition> - <property name="java.lib.dir.platform" value="/System/Library/Frameworks/JavaVM.framework/Libraries" /> + <!-- Fallback value Java6 --> + <property name="java.includes.dir.platform" value="/System/Library/Frameworks/JavaVM.framework/Headers" /> + <property name="java.lib.dir.platform" value="/System/Library/Frameworks/JavaVM.framework/Libraries" /> + <echo message="java.includes.dir.platform ${java.includes.dir.platform}" /> + <echo message="java.lib.dir.platform ${java.lib.dir.platform}" /> </target> <target name="gluegen.cpptasks.declare.compiler.freebsd.x86" if="isFreeBSDX86"> diff --git a/make/jogamp-env.xml b/make/jogamp-env.xml index 07083c7..77421f5 100755 --- a/make/jogamp-env.xml +++ b/make/jogamp-env.xml @@ -27,6 +27,16 @@ <echo message="java.version ${java.version}"/> <echo message="java.home ${java.home}"/> + <property name="jvmJava.exe" value="${java.home}/bin/java" /> <!-- the java jvm executable for unit tests --> + <echo message="jvmJava.exe ${jvmJava.exe}"/> + + <condition property="jvmJava7.exe" value="${env.JAVA7_EXE}"> + <not> + <equals arg1="${env.JAVA7_EXE}" arg2="$${env.JAVA7_EXE}" casesensitive="true" /> + </not> + </condition> + <echo message="jvmJava7.exe ${jvmJava7.exe}"/> <!-- optional extra Java7 JVM for unit tests --> + <fail message="Please build using Ant 1.8.0 or higher."> <condition> <not> @@ -42,6 +52,8 @@ <contains string="${ant.java.version}" substring="1.6" casesensitive="false" /> <contains string="${ant.java.version}" substring="1.7" casesensitive="false" /> <contains string="${ant.java.version}" substring="1.8" casesensitive="false" /> + <contains string="${ant.java.version}" substring="1.9" casesensitive="false" /> + <contains string="${ant.java.version}" substring="2.0" casesensitive="false" /> </or> </not> </condition> @@ -52,10 +64,9 @@ <target name="jogamp.env.init" depends="jogamp.env.validation"> <property environment="env" /> + <!-- only set 'junit.is.disabled' if set in environment as 'true' to disable JUNIT tests --> <condition property="junit.is.disabled" value="${env.JUNIT_DISABLED}"> - <not> - <equals arg1="${env.JUNIT_DISABLED}" arg2="$${env.JUNIT_DISABLED}" casesensitive="true" /> - </not> + <istrue value="${env.JUNIT_DISABLED}"/> </condition> <echo message="junit.is.disabled ${junit.is.disabled}"/> @@ -72,7 +83,7 @@ </condition> <property name="junit.run.arg1" value="-Djunit.run.arg1=dummy" /> <!-- default dummy values --> - <!-- only set 'build.archiveon' if set in environment to trigger archive creation --> + <!-- only set 'build.archiveon' if set in environment as 'true' to trigger archive creation --> <condition property="build.archiveon" value="${env.BUILD_ARCHIVE}"> <istrue value="${env.BUILD_ARCHIVE}"/> </condition> @@ -136,30 +147,51 @@ <property name="target.sourcelevel" value="${ant.java.version}" /> <!-- default fallback values --> <property name="target.targetlevel" value="${ant.java.version}" /> <!-- default fallback values --> + <!-- default value for std Java --> + <condition property="target.rt.jar" + value="${java.home}/lib/rt.jar"> + <available file="${java.home}/lib/rt.jar"/> + </condition> <!-- default fallback value on OS X --> - <available property="target.rt.jar" - type="file" - file="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar" - value="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"/> + <condition property="target.rt.jar" + value="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"> + <available file="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"/> + </condition> <!-- default fallback value on std Java --> - <property name="target.rt.jar" value="${java.home}/lib/rt.jar" /> <echo message="target.user.set ${target.user.set}"/> <echo message="target.sourcelevel ${target.sourcelevel}"/> <echo message="target.targetlevel ${target.targetlevel}"/> <echo message="target.rt.jar ${target.rt.jar}"/> + <fail message="No target.rt.jar specified not found."> + <condition> + <not> + <isset property="target.rt.jar"/> + </not> + </condition> + </fail> <property name="host.sourcelevel" value="${ant.java.version}" /> <!-- default values for compile time components --> <property name="host.targetlevel" value="${ant.java.version}" /> <!-- default values for compile time components --> - <!-- default fallback value for compile time components on OS X --> - <available property="host.rt.jar" - type="file" - file="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar" - value="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"/> - <!-- default fallback value for compile time components on std Java --> - <property name="host.rt.jar" value="${java.home}/lib/rt.jar" /> + <!-- default value for std Java --> + <condition property="host.rt.jar" + value="${java.home}/lib/rt.jar"> + <available file="${java.home}/lib/rt.jar"/> + </condition> + <!-- default fallback value on OS X --> + <condition property="host.rt.jar" + value="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"> + <available file="/System/Library/Frameworks/JavaVM.framework/Versions/${ant.java.version}/Classes/classes.jar"/> + </condition> <echo message="host.sourcelevel ${host.sourcelevel}"/> <echo message="host.targetlevel ${host.targetlevel}"/> <echo message="host.rt.jar ${host.rt.jar}"/> + <fail message="No host.rt.jar specified not found."> + <condition> + <not> + <isset property="host.rt.jar"/> + </not> + </condition> + </fail> <fail message="Unsupported Target Java version (sourcelevel): ${target.sourcelevel}. Make sure that the version of the Java compiler is 1.6 (6.0) or greater."> <condition> @@ -201,6 +233,7 @@ <echo message="junit.run.arg0 ${junit.run.arg0}"/> <echo message="junit.run.arg1 ${junit.run.arg1}"/> + </target> </project> diff --git a/make/scripts/make.gluegen.all.macosx-java7.sh b/make/scripts/make.gluegen.all.macosx-java7.sh index 6ffefc4..1a69f9e 100755 --- a/make/scripts/make.gluegen.all.macosx-java7.sh +++ b/make/scripts/make.gluegen.all.macosx-java7.sh @@ -19,4 +19,4 @@ ant \ -Dtarget.targetlevel=1.6 \ -Dtarget.rt.jar=/opt-share/jre1.6.0_30/lib/rt.jar \ -Drootrel.build=build-macosx-java7 \ - $* 2>&1 | tee make.gluegen.all.macosx.log + $* 2>&1 | tee make.gluegen.all.macosx-java7.log diff --git a/make/stub_includes/jni/macosx/jawt_md.h b/make/stub_includes/jni/macosx/jawt_md.h new file mode 100644 index 0000000..e65474b --- /dev/null +++ b/make/stub_includes/jni/macosx/jawt_md.h @@ -0,0 +1,68 @@ +/** + * Temporary workaround! + * + * Provided darwin/jawt_md.h from Oracle for OSX / Java7 + * has X11 dependencies and does not define JAWT_SurfaceLayers. + * + * This C header file is derived from Apple's Java SDK provided C header file + * with the following copyright notice: + * + * Copyright (c) 2002 Apple computer Inc. All rights reserved. + * + * This version has complex comments removed and does not contain inlined algorithms etc, if any existed. + * + * The original C header file was included to JOGL on Mon Jun 15 22:57:38 2009 + * (commit cbc45e816f4ee81031bffce19a99550681462a24) by Sun Microsystem's staff and were approved. + * + * This C header file is included due to ensure compatibility with - and invocation of the JAWT protocol. + * They are processed by GlueGen to create a Java binding for JAWT invocation only. + * + * http://ftp.resource.org/courts.gov/c/F3/387/387.F3d.522.03-5400.html (36) + * "Atari Games Corp. v. Nintendo of Am., Inc., Nos. 88-4805 & 89-0027, 1993 WL 207548, at *1 (N.D.Cal. May 18, 1993) ("Atari III") + * ("Program code that is strictly necessary to achieve current compatibility presents a merger problem, almost by definition, + * and is thus excluded from the scope of any copyright.")." + * + * http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=OJ:L:2009:111:0016:0022:EN:PDF + * L 111/17 (10) and (15) + */ + +#ifndef _JAVASOFT_JAWT_MD_H_ +#define _JAVASOFT_JAWT_MD_H_ + +#include <jawt.h> +#include <AppKit/NSView.h> +#include <QuartzCore/CALayer.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * JAWT_DrawingSurfaceInfo.getPlatformInfo() + * + * Only if not JAWT_SurfaceLayers, see below! + */ +typedef struct JAWT_MacOSXDrawingSurfaceInfo +{ + /** the view is guaranteed to be valid only for the duration of Component.paint method */ + NSView *cocoaViewRef; +} +JAWT_MacOSXDrawingSurfaceInfo; + +#ifndef __GLUEGEN__ + + #define JAWT_MACOSX_USE_CALAYER 0x80000000 + + /** Java7 and Java6 (OSX >= 10.6.4) CALayer surface if provided (Bit JAWT_MACOSX_USE_CALAYER set in the JAWT version) */ + @protocol JAWT_SurfaceLayers + @property (readwrite, retain) CALayer *layer; + @property (readonly) CALayer *windowLayer; + @end + +#endif __GLUEGEN__ + +#ifdef __cplusplus +} +#endif + +#endif /* !_JAVASOFT_JAWT_MD_H_ */ diff --git a/make/stub_includes/jni/macosx/jni_md.h b/make/stub_includes/jni/macosx/jni_md.h new file mode 100644 index 0000000..7f52704 --- /dev/null +++ b/make/stub_includes/jni/macosx/jni_md.h @@ -0,0 +1,47 @@ +/* + * Temporary workaround! + * + * Provided darwin/jawt_md.h from Oracle for OSX / Java7 + * has X11 dependencies and does not define JAWT_SurfaceLayers. + * + * @(#)jni_md.h 1.18 03/12/19 + * + * This C header file is derived from Sun Microsystem's Java SDK provided C header file + * with the following copyright notice: + * + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. + * + * This version has complex comments removed and does not contain inlined algorithms etc, if any existed. + * + * The original C header file was included to JOGL on Sat Jun 21 02:10:30 2008 + * (commit cbc45e816f4ee81031bffce19a99550681462a24) by Sun Microsystem's staff and were approved. + * + * This C header file is included due to ensure compatibility with - and invocation of the JAWT protocol. + * They are processed by GlueGen to create a Java binding for JAWT invocation only. + * + * http://ftp.resource.org/courts.gov/c/F3/387/387.F3d.522.03-5400.html (36) + * "Atari Games Corp. v. Nintendo of Am., Inc., Nos. 88-4805 & 89-0027, 1993 WL 207548, at *1 (N.D.Cal. May 18, 1993) ("Atari III") + * ("Program code that is strictly necessary to achieve current compatibility presents a merger problem, almost by definition, + * and is thus excluded from the scope of any copyright.")." + * + * http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=OJ:L:2009:111:0016:0022:EN:PDF + * L 111/17 (10) and (15) + */ + +#ifndef _JAVASOFT_JNI_MD_H_ +#define _JAVASOFT_JNI_MD_H_ + +#define JNIEXPORT __attribute__((visibility("default"))) +#define JNIIMPORT +#define JNICALL + +#if __LP64__ +typedef int jint; +#else +typedef long jint; +#endif +typedef long long jlong; +typedef signed char jbyte; + +#endif /* !_JAVASOFT_JNI_MD_H_ */ 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..35720a0 --- /dev/null +++ b/src/java/com/jogamp/common/util/FunctionTask.java @@ -0,0 +1,164 @@ +/** + * 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 final Function<R,A> getRunnable() { + return runnable; + } + + /** + * Sets the arguments for {@link #run()}. + * They will be cleared after calling {@link #run()} or {@link #eval(Object...)}. + */ + public final void setArgs(A... args) { + this.args = args; + } + + /** + * Retrieves the cached result of {@link #run()} + * and is cleared within this method. + */ + public final 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 final void run() { + final A[] args = this.args; + this.args = null; + this.result = null; + tStarted = System.currentTimeMillis(); + if(null == syncObject) { + try { + this.result = runnable.eval(args); + } catch (Throwable t) { + runnableException = t; + if(!catchExceptions) { + throw new RuntimeException(runnableException); + } + } finally { + tExecuted = System.currentTimeMillis(); + } + } else { + synchronized (syncObject) { + try { + this.result = runnable.eval(args); + } catch (Throwable t) { + runnableException = t; + if(!catchExceptions) { + throw new RuntimeException(runnableException); + } + } finally { + tExecuted = System.currentTimeMillis(); + syncObject.notifyAll(); + } + } + } + } + + @Override + public final R eval(A... args) { + this.args = args; + run(); + final R res = result; + result = null; + return res; + } +} + diff --git a/src/java/com/jogamp/common/util/RunnableTask.java b/src/java/com/jogamp/common/util/RunnableTask.java index b0ce159..5d9441a 100644 --- a/src/java/com/jogamp/common/util/RunnableTask.java +++ b/src/java/com/jogamp/common/util/RunnableTask.java @@ -32,87 +32,58 @@ 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 */ - public Runnable getRunnable() { + public final 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. - */ - public void setAttachment(Object o) { - attachment = o; - } - - /** - * Return the attachment object if any. - * @see #setAttachment(Object) - */ - public Object getAttachment() { - return attachment; - } - - public void run() { + @Override + public final void run() { tStarted = System.currentTimeMillis(); if(null == syncObject) { try { @@ -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..d2a924f --- /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 final Object getSyncObject() { + return syncObject; + } + + /** + * Attach a custom object to this task. + * Useful to piggybag further information, ie tag a task final. + */ + public final void setAttachment(Object o) { + attachment = o; + } + + /** + * Return the attachment object if any. + * @see #setAttachment(Object) + */ + public final 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 final void flush() { + if(!isExecuted() && hasWaiter()) { + synchronized (syncObject) { + isFlushed = true; + syncObject.notifyAll(); + } + } + } + + /** + * @return !{@link #isExecuted()} && !{@link #isFlushed()} + */ + public final boolean isInQueue() { return 0 != tExecuted && !isFlushed; } + + /** + * @return True if executed, otherwise false; + */ + public final boolean isExecuted() { return 0 != tExecuted ; } + + /** + * @return True if flushed, otherwise false; + */ + public final boolean isFlushed() { return isFlushed; } + + /** + * @return True if invoking thread waits until done, + * ie a <code>notifyObject</code> was passed, otherwise false; + */ + public final 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 final Throwable getThrowable() { return runnableException; } + + public final long getTimestampCreate() { return tCreated; } + public final long getTimestampBeforeExec() { return tStarted; } + public final long getTimestampAfterExec() { return tExecuted; } + public final long getDurationInQueue() { return tStarted - tCreated; } + public final long getDurationInExec() { return tExecuted - tStarted; } + public final 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+"]"; + } +} + |