summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKenneth Russel <[email protected]>2006-02-23 08:02:08 +0000
committerKenneth Russel <[email protected]>2006-02-23 08:02:08 +0000
commit5fbc462246a5d40833697902e84f2b2076e735a2 (patch)
treee9072221589216aabd499316efdf6e7296f9dd91
parent76e7d4bd24490eb73914fa7461baf86da17f584d (diff)
Added mechanism for kicking the current context off the
GLWorkerThread. Tested with modified version of demos.texture.TestTexture doing the loading in another thread with manual makeCurrent()/release() calls (not recommended style). git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/trunk@634 232f8b59-042b-4e1e-8c03-345bb8c30851
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextImpl.java10
-rw-r--r--src/classes/com/sun/opengl/impl/GLContextLock.java8
-rwxr-xr-xsrc/classes/com/sun/opengl/impl/GLWorkerThread.java79
3 files changed, 84 insertions, 13 deletions
diff --git a/src/classes/com/sun/opengl/impl/GLContextImpl.java b/src/classes/com/sun/opengl/impl/GLContextImpl.java
index a4eee6652..4a6885f45 100644
--- a/src/classes/com/sun/opengl/impl/GLContextImpl.java
+++ b/src/classes/com/sun/opengl/impl/GLContextImpl.java
@@ -96,6 +96,12 @@ public abstract class GLContextImpl extends GLContext {
}
}
+ if (GLWorkerThread.isStarted() &&
+ !GLWorkerThread.isWorkerThread()) {
+ // Kick the GLWorkerThread off its current context
+ GLWorkerThread.invokeLater(new Runnable() { public void run() {} });
+ }
+
lock.lock();
int res = 0;
try {
@@ -345,4 +351,8 @@ public abstract class GLContextImpl extends GLContext {
public GLObjectTracker getObjectTracker() {
return tracker;
}
+
+ public boolean hasWaiters() {
+ return lock.hasWaiters();
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/GLContextLock.java b/src/classes/com/sun/opengl/impl/GLContextLock.java
index 9fb4d66e5..753ef14f8 100644
--- a/src/classes/com/sun/opengl/impl/GLContextLock.java
+++ b/src/classes/com/sun/opengl/impl/GLContextLock.java
@@ -52,6 +52,7 @@ public class GLContextLock {
private Object lock = new Object();
private Thread owner;
private boolean failFastMode = true;
+ private volatile int waiters;
/** Locks this GLContextLock on the current thread. If fail fast
mode is enabled and the GLContextLock is already owned by
@@ -68,9 +69,12 @@ public class GLContextLock {
" which is already current on thread " + owner);
} else {
try {
+ ++waiters;
lock.wait();
} catch (InterruptedException e) {
throw new GLException(e);
+ } finally {
+ --waiters;
}
}
}
@@ -115,4 +119,8 @@ public class GLContextLock {
public boolean getFailFastMode() {
return failFastMode;
}
+
+ public boolean hasWaiters() {
+ return (waiters != 0);
+ }
}
diff --git a/src/classes/com/sun/opengl/impl/GLWorkerThread.java b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
index 4091d1a77..57938c8bc 100755
--- a/src/classes/com/sun/opengl/impl/GLWorkerThread.java
+++ b/src/classes/com/sun/opengl/impl/GLWorkerThread.java
@@ -41,6 +41,7 @@ package com.sun.opengl.impl;
import java.lang.reflect.InvocationTargetException;
import java.security.*;
+import java.util.*;
import javax.media.opengl.*;
/** Singleton thread upon which all OpenGL work is performed by
@@ -61,9 +62,10 @@ public class GLWorkerThread {
private static volatile boolean shouldTerminate;
private static volatile Throwable exception;
- // The Runnable to execute on the worker thread -- no need for a
- // queue since we don't have an invokeLater() primitive
+ // The Runnable to execute immediately on the worker thread
private static volatile Runnable work;
+ // Queue of Runnables to be asynchronously invoked
+ private static List queue = new LinkedList();
/** Should only be called by Threading class if creation of the
GLWorkerThread was requested via the opengl.1thread system
@@ -162,14 +164,35 @@ public class GLWorkerThread {
}
work = runnable;
- lock.notifyAll();
- lock.wait();
+ lockTemp.notifyAll();
+ lockTemp.wait();
if (exception != null) {
throw new InvocationTargetException(exception);
}
}
}
+ public static void invokeLater(Runnable runnable) {
+ if (!started) {
+ throw new RuntimeException("May not invokeLater on worker thread without starting it first");
+ }
+
+ Object lockTemp = lock;
+ if (lockTemp == null) {
+ return; // Terminating
+ }
+
+ synchronized (lockTemp) {
+ if (thread == null) {
+ // Terminating
+ return;
+ }
+
+ queue.add(runnable);
+ lockTemp.notifyAll();
+ }
+ }
+
/** Indicates whether the OpenGL worker thread was started, i.e.,
whether it is currently in use. */
public static boolean isStarted() {
@@ -191,11 +214,19 @@ public class GLWorkerThread {
while (!shouldTerminate) {
synchronized (lock) {
- while ((work == null) && !shouldTerminate) {
+ while (!shouldTerminate &&
+ (work == null) &&
+ queue.isEmpty()) {
try {
- lock.wait();
+ // Avoid race conditions with wanting to release contexts on this thread
+ lock.wait(1000);
} catch (InterruptedException e) {
}
+
+ if (GLContext.getCurrent() != null) {
+ // Test later to see whether we need to release this context
+ break;
+ }
}
if (shouldTerminate) {
@@ -205,13 +236,35 @@ public class GLWorkerThread {
return;
}
- try {
- work.run();
- } catch (Throwable t) {
- exception = t;
- } finally {
- work = null;
- lock.notifyAll();
+ if (work != null) {
+ try {
+ work.run();
+ } catch (Throwable t) {
+ exception = t;
+ } finally {
+ work = null;
+ lock.notifyAll();
+ }
+ }
+
+ while (!queue.isEmpty()) {
+ try {
+ Runnable curAsync = (Runnable) queue.remove(0);
+ curAsync.run();
+ } catch (Throwable t) {
+ System.out.println("Exception occurred on JOGL OpenGL worker thread:");
+ t.printStackTrace();
+ }
+ }
+
+ // See about releasing current context
+ GLContext curContext = GLContext.getCurrent();
+ if (curContext != null &&
+ (curContext instanceof GLContextImpl)) {
+ GLContextImpl impl = (GLContextImpl) curContext;
+ if (impl.hasWaiters()) {
+ impl.release();
+ }
}
}
}