summaryrefslogtreecommitdiffstats
path: root/src/nativewindow/classes
diff options
context:
space:
mode:
Diffstat (limited to 'src/nativewindow/classes')
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java34
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java83
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java8
-rw-r--r--src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java178
-rw-r--r--src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java12
5 files changed, 167 insertions, 148 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java
index fd2478ab2..203ae3d12 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/LockingNativeWindowFactory.java
@@ -35,39 +35,7 @@ package com.jogamp.nativewindow.impl;
import javax.media.nativewindow.*;
public class LockingNativeWindowFactory extends NativeWindowFactoryImpl {
- // Provides a generic basic and recursive locking mechanism for your discretion.
- private ToolkitLock toolkitLock = new ToolkitLock() {
- private Thread owner;
- private int recursionCount;
-
- public synchronized void lock() {
- Thread cur = Thread.currentThread();
- if (owner == cur) {
- ++recursionCount;
- return;
- }
- while (owner != null) {
- try {
- wait();
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
- owner = cur;
- }
-
- public synchronized void unlock() {
- if (owner != Thread.currentThread()) {
- throw new RuntimeException("Not owner");
- }
- if (recursionCount > 0) {
- --recursionCount;
- return;
- }
- owner = null;
- notifyAll();
- }
- };
+ private ToolkitLock toolkitLock = new RecursiveToolkitLock();
public ToolkitLock getToolkitLock() {
return toolkitLock;
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java
new file mode 100644
index 000000000..06ce54368
--- /dev/null
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java
@@ -0,0 +1,83 @@
+package com.jogamp.nativewindow.impl;
+
+import javax.media.nativewindow.*;
+
+//
+// Reentrance locking toolkit
+//
+public class RecursiveToolkitLock implements ToolkitLock {
+ private Thread owner;
+ private int recursionCount;
+ private Exception lockedStack = null;
+ private static final long timeout = 3000; // maximum wait 3s
+
+ public Exception getLockedStack() {
+ return lockedStack;
+ }
+
+ public Thread getOwner() {
+ return owner;
+ }
+
+ public boolean isOwner() {
+ return isOwner(Thread.currentThread());
+ }
+
+ public synchronized boolean isOwner(Thread thread) {
+ return owner == thread ;
+ }
+
+ public synchronized boolean isLocked() {
+ return null != owner;
+ }
+
+ /** Recursive and blocking lockSurface() implementation */
+ public synchronized void lock() {
+ Thread cur = Thread.currentThread();
+ if (owner == cur) {
+ ++recursionCount;
+ return;
+ }
+
+ long ts = System.currentTimeMillis();
+ while (owner != null && (System.currentTimeMillis()-ts) < timeout) {
+ try {
+ wait(timeout);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ if(owner != null) {
+ lockedStack.printStackTrace();
+ throw new RuntimeException("Waited "+timeout+"ms for: "+owner+" - "+cur);
+ }
+ owner = cur;
+ lockedStack = new Exception("Previously locked by "+owner);
+ }
+
+
+ /** Recursive and unblocking unlockSurface() implementation */
+ public synchronized void unlock() {
+ unlock(null);
+ }
+
+ /** Recursive and unblocking unlockSurface() implementation */
+ public synchronized void unlock(Runnable releaseAfterUnlockBeforeNotify) {
+ Thread cur = Thread.currentThread();
+ if (owner != cur) {
+ lockedStack.printStackTrace();
+ throw new RuntimeException(cur+": Not owner, owner is "+owner);
+ }
+ if (recursionCount > 0) {
+ --recursionCount;
+ return;
+ }
+ owner = null;
+ lockedStack = null;
+ if(null!=releaseAfterUnlockBeforeNotify) {
+ releaseAfterUnlockBeforeNotify.run();
+ }
+ notifyAll();
+ }
+}
+
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java
index a6f52f3c0..0cd02558a 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11GraphicsConfigurationFactory.java
@@ -58,7 +58,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
int num[] = { -1 };
long display = screen.getDevice().getHandle();
- X11Lib.XLockDisplay(display);
+ X11Util.XLockDisplay(display);
try {
XVisualInfo[] xvis = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualIDMask|X11Lib.VisualScreenMask, xvi_temp, num, 0);
@@ -68,7 +68,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return XVisualInfo.create(xvis[0]);
} finally {
- X11Lib.XUnlockDisplay(display);
+ X11Util.XUnlockDisplay(display);
}
}
@@ -90,7 +90,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
vinfo_template.setC_class(c_class);
long display = screen.getDevice().getHandle();
- X11Lib.XLockDisplay(display);
+ X11Util.XLockDisplay(display);
try {
XVisualInfo[] vinfos = X11Lib.XGetVisualInfoCopied(display, X11Lib.VisualScreenMask, vinfo_template, num, 0);
XVisualInfo best=null;
@@ -111,7 +111,7 @@ public class X11GraphicsConfigurationFactory extends GraphicsConfigurationFactor
return ret;
} finally {
- X11Lib.XUnlockDisplay(display);
+ X11Util.XUnlockDisplay(display);
}
}
}
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java
index 5f5c10885..d93302e57 100644
--- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java
+++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/x11/X11Util.java
@@ -37,6 +37,7 @@ import java.util.Map;
import java.util.Collection;
import java.util.ArrayList;
import java.util.Iterator;
+import com.jogamp.common.util.LongObjectHashMap;
import javax.media.nativewindow.*;
@@ -51,25 +52,29 @@ import com.jogamp.nativewindow.impl.*;
*/
public class X11Util {
private static final boolean DEBUG = Debug.debug("X11Util");
+ private static final boolean DEBUG_XDISPLAY_LOCK = false;
static {
NWJNILibLoader.loadNativeWindow("x11");
- installIOErrorHandler();
+ initialize();
}
- private X11Util() {}
+ public static void initSingleton() {
+ // just exist to ensure static init has been run
+ }
- private static ThreadLocal currentDisplayMap = new ThreadLocal();
+ private X11Util() {}
// not exactly thread safe, but good enough for our purpose,
// which is to tag a NamedDisplay uncloseable after creation.
private static Object globalLock = new Object();
- private static Collection globalNamedDisplayActive = new ArrayList();
- private static Collection globalNamedDisplayPassive = new ArrayList();
+ private static LongObjectHashMap globalNamedDisplayMap = new LongObjectHashMap();
+
+ private static ThreadLocal currentDisplayMap = new ThreadLocal();
public static final String nullDeviceName = "nil" ;
- public static class NamedDisplay implements Cloneable {
+ public static class NamedDisplay extends RecursiveToolkitLock implements Cloneable {
String name;
long handle;
int refCount;
@@ -102,10 +107,9 @@ public class X11Util {
*/
public static int shutdown(boolean realXClosePendingDisplays, boolean verbose) {
int num=0;
- String msg;
+ String msg = null;
if(DEBUG||verbose) {
- msg = "X11Util.Display: Shutdown (active: "+globalNamedDisplayActive.size()+
- ", passive: "+globalNamedDisplayPassive.size() + ")";
+ msg = "X11Util.Display: Shutdown (global: "+globalNamedDisplayMap.size()+ ")" ;
if(DEBUG) {
Exception e = new Exception(msg);
e.printStackTrace();
@@ -114,36 +118,8 @@ public class X11Util {
}
}
- msg = realXClosePendingDisplays ? "Close" : "Keep" ;
-
synchronized(globalLock) {
- // for all passive displays ..
- Collection namedDisplays = globalNamedDisplayPassive;
- globalNamedDisplayPassive = new ArrayList();
- for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) {
- NamedDisplay ndpy = (NamedDisplay)iter.next();
- if(DEBUG||verbose) {
- System.err.println(msg+" passive: "+ndpy);
- }
- if(realXClosePendingDisplays) {
- X11Lib.XCloseDisplay(ndpy.getHandle());
- }
- num++;
- }
-
- // for all active displays ..
- namedDisplays = globalNamedDisplayActive;
- globalNamedDisplayActive = new ArrayList();
- for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) {
- NamedDisplay ndpy = (NamedDisplay)iter.next();
- if(DEBUG||verbose) {
- System.err.println(msg+" active: "+ndpy);
- }
- if(realXClosePendingDisplays) {
- X11Lib.XCloseDisplay(ndpy.getHandle());
- }
- num++;
- }
+ globalNamedDisplayMap.clear();
}
return num;
}
@@ -162,24 +138,14 @@ public class X11Util {
public static long createThreadLocalDisplay(String name) {
NamedDisplay namedDpy = getCurrentDisplay(name);
if(null==namedDpy) {
- synchronized(globalLock) {
- namedDpy = getNamedDisplay(globalNamedDisplayPassive, name);
- if(null != namedDpy) {
- if(!globalNamedDisplayPassive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); }
- globalNamedDisplayActive.add(namedDpy);
- addCurrentDisplay( namedDpy );
- }
- }
- }
- if(null==namedDpy) {
long dpy = X11Lib.XOpenDisplay(name);
if(0==dpy) {
throw new NativeWindowException("X11Util.Display: Unable to create a display("+name+") connection in Thread "+Thread.currentThread().getName());
}
namedDpy = new NamedDisplay(name, dpy);
+ addCurrentDisplay( namedDpy );
synchronized(globalLock) {
- globalNamedDisplayActive.add(namedDpy);
- addCurrentDisplay( namedDpy );
+ globalNamedDisplayMap.put(dpy, namedDpy);
}
if(DEBUG) {
Exception e = new Exception("X11Util.Display: Created new TLS "+namedDpy+" in thread "+Thread.currentThread().getName());
@@ -203,7 +169,7 @@ public class X11Util {
public static long closeThreadLocalDisplay(String name) {
NamedDisplay namedDpy = getCurrentDisplay(name);
if(null==namedDpy) {
- throw new RuntimeException("X11Util.Display: Display("+name+") with given handle is not mapped to TLS in thread "+Thread.currentThread().getName());
+ throw new RuntimeException("X11Util.Display: Display("+name+") with given name is not mapped to TLS in thread "+Thread.currentThread().getName());
}
if(0==namedDpy.refCount) {
throw new RuntimeException("X11Util.Display: "+namedDpy+" has refCount already 0 in thread "+Thread.currentThread().getName());
@@ -211,20 +177,18 @@ public class X11Util {
long dpy = namedDpy.getHandle();
namedDpy.refCount--;
if(0==namedDpy.refCount) {
- synchronized(globalLock) {
- if(!globalNamedDisplayActive.remove(namedDpy)) { throw new RuntimeException("Internal: "+namedDpy); }
- if(namedDpy.isUncloseable()) {
- globalNamedDisplayPassive.add(namedDpy);
- } else {
- X11Lib.XCloseDisplay(dpy);
- }
- removeCurrentDisplay(namedDpy);
- }
if(DEBUG) {
String type = namedDpy.isUncloseable() ? "passive" : "real" ;
Exception e = new Exception("X11Util.Display: Closing ( "+type+" ) TLS "+namedDpy+" in thread "+Thread.currentThread().getName());
e.printStackTrace();
}
+ removeCurrentDisplay(namedDpy);
+ synchronized(globalLock) {
+ if(null==globalNamedDisplayMap.remove(dpy)) { throw new RuntimeException("Internal: "+namedDpy); }
+ }
+ if(!namedDpy.isUncloseable()) {
+ X11Lib.XCloseDisplay(dpy);
+ }
} else if(DEBUG) {
Exception e = new Exception("X11Util.Display: Keep TLS "+namedDpy+" in thread "+Thread.currentThread().getName());
e.printStackTrace();
@@ -232,39 +196,64 @@ public class X11Util {
return dpy;
}
- public static String getThreadLocalDisplayName(long handle) {
- NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle);
- return null != ndpy ? ndpy.getName() : null;
+ public static long closeThreadLocalDisplay(long handle) {
+ NamedDisplay ndpy;
+ synchronized(globalLock) {
+ ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle);
+ }
+ if(null==ndpy) {
+ throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, in thread "+Thread.currentThread().getName());
+ }
+ return closeThreadLocalDisplay(ndpy.getName());
}
- public static boolean markThreadLocalDisplayUndeletable(long handle) {
- NamedDisplay ndpy = getNamedDisplay(getCurrentDisplayMapImpl().values(), handle);
- if( null != ndpy ) {
- ndpy.unCloseable=true;
- return true;
+ public static void XLockDisplay(long handle) {
+ if(DEBUG_XDISPLAY_LOCK) {
+ NamedDisplay ndpy;
+ synchronized(globalLock) {
+ ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle);
+ }
+ if(null==ndpy) {
+ throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName());
+ }
+ ndpy.lock();
+ try {
+ X11Lib.XLockDisplay(handle);
+ } catch (Throwable t) {
+ ndpy.unlock();
+ throw new RuntimeException(t);
+ }
+ } else {
+ X11Lib.XLockDisplay(handle);
}
- return false;
}
- public static String getGlobalDisplayName(long handle, boolean active) {
- String name;
- synchronized(globalLock) {
- NamedDisplay ndpy = getNamedDisplay(active ? globalNamedDisplayActive : globalNamedDisplayPassive, handle);
- name = null != ndpy ? ndpy.getName() : null;
+ public static void XUnlockDisplay(long handle) {
+ if(DEBUG_XDISPLAY_LOCK) {
+ NamedDisplay ndpy;
+ synchronized(globalLock) {
+ ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle);
+ }
+ if(null==ndpy) {
+ throw new RuntimeException("X11Util.Display: Display(0x"+Long.toHexString(handle)+") with given handle is not mapped, thread "+Thread.currentThread().getName());
+ }
+ X11Lib.XUnlockDisplay(handle);
+ ndpy.unlock();
+ } else {
+ X11Lib.XUnlockDisplay(handle);
}
- return name;
}
- public static boolean markGlobalDisplayUndeletable(long handle) {
- boolean r=false;
+ public static boolean markThreadLocalDisplayUncloseable(long handle) {
+ NamedDisplay ndpy;
synchronized(globalLock) {
- NamedDisplay ndpy = getNamedDisplay(globalNamedDisplayActive, handle);
- if( null != ndpy ) {
- ndpy.unCloseable=true;
- r=true;
- }
+ ndpy = (NamedDisplay) globalNamedDisplayMap.get(handle);
+ }
+ if( null != ndpy ) {
+ ndpy.unCloseable=true;
+ return true;
}
- return r;
+ return false;
}
private static Map getCurrentDisplayMapImpl() {
@@ -309,26 +298,5 @@ public class X11Util {
return (NamedDisplay) displayMap.get(name);
}
- private static NamedDisplay getNamedDisplay(Collection namedDisplays, String name) {
- if(null==name) name=nullDeviceName;
- for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) {
- NamedDisplay ndpy = (NamedDisplay)iter.next();
- if (ndpy.getNameSafe().equals(name)) {
- return ndpy;
- }
- }
- return null;
- }
-
- private static NamedDisplay getNamedDisplay(Collection namedDisplays, long handle) {
- for(Iterator iter=namedDisplays.iterator(); iter.hasNext(); ) {
- NamedDisplay ndpy = (NamedDisplay)iter.next();
- if (ndpy.getHandle()==handle) {
- return ndpy;
- }
- }
- return null;
- }
-
- private static native void installIOErrorHandler();
+ private static native void initialize();
}
diff --git a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java
index 58b40efe0..a18ee91c2 100644
--- a/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java
+++ b/src/nativewindow/classes/javax/media/nativewindow/x11/X11GraphicsScreen.java
@@ -59,12 +59,12 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
NativeWindowFactory.getDefaultFactory().getToolkitLock().lock();
try {
long display = X11Util.createThreadLocalDefaultDisplay();
- X11Lib.XLockDisplay(display);
+ X11Util.XLockDisplay(display);
try{
int scrnIdx = X11Lib.DefaultScreen(display);
return createScreenDevice(display, scrnIdx);
}finally{
- X11Lib.XUnlockDisplay(display);
+ X11Util.XUnlockDisplay(display);
}
} finally {
NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock();
@@ -76,12 +76,12 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
NativeWindowFactory.getDefaultFactory().getToolkitLock().lock();
try {
long display = getDevice().getHandle();
- X11Lib.XLockDisplay(display);
+ X11Util.XLockDisplay(display);
try{
int scrnIdx = X11Lib.DefaultScreen(display);
return X11Lib.DefaultVisualID(display, scrnIdx);
}finally{
- X11Lib.XUnlockDisplay(display);
+ X11Util.XUnlockDisplay(display);
}
} finally {
NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock();
@@ -93,13 +93,13 @@ public class X11GraphicsScreen extends DefaultGraphicsScreen implements Cloneabl
NativeWindowFactory.getDefaultFactory().getToolkitLock().lock();
try {
long display = device.getHandle();
- X11Lib.XLockDisplay(display);
+ X11Util.XLockDisplay(display);
try{
if(X11Lib.XineramaEnabled(display)) {
screen = 0; // Xinerama -> 1 screen
}
}finally{
- X11Lib.XUnlockDisplay(display);
+ X11Util.XUnlockDisplay(display);
}
} finally {
NativeWindowFactory.getDefaultFactory().getToolkitLock().unlock();