diff options
-rw-r--r-- | src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java | 168 |
1 files changed, 101 insertions, 67 deletions
diff --git a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java index a894c61..bfa3d32 100644 --- a/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java +++ b/src/nativewindow/classes/com/jogamp/nativewindow/impl/RecursiveToolkitLock.java @@ -34,110 +34,144 @@ import javax.media.nativewindow.*; // Reentrance locking toolkit // public class RecursiveToolkitLock { - private Thread owner = null; - private int recursionCount = 0; - private Exception lockedStack = null; - private static final long timeout = 5000; // maximum wait 5s - // private static final long timeout = 300000; // maximum wait 300s + static class SyncData { + Thread owner = null; + int recursionCount = 0; + Exception lockedStack = null; + } + private SyncData sdata = new SyncData(); // synchronized (flow/mem) mutable access + + private long timeout; + private static final long defaultTimeout = 5000; // default maximum wait 5s + // private static final long defaultTimeout = 10000; // default maximum wait 10s + // private static final long defaultTimeout = 300000; // default maximum wait 300s / 5min private static final boolean TRACE_LOCK = Debug.debug("TraceLock"); - public Exception getLockedStack() { - return lockedStack; + public RecursiveToolkitLock() { + this.timeout = defaultTimeout; } - public Thread getOwner() { - return owner; + public RecursiveToolkitLock(long timeout) { + this.timeout = timeout; } - public boolean isOwner() { - return isOwner(Thread.currentThread()); + public final Exception getLockedStack() { + synchronized(sdata) { + return sdata.lockedStack; + } } - public synchronized boolean isOwner(Thread thread) { - return owner == thread ; + public final Thread getOwner() { + synchronized(sdata) { + return sdata.owner; + } } - public synchronized boolean isLocked() { - return null != owner; + public final boolean isOwner() { + return isOwner(Thread.currentThread()); } - public synchronized boolean isLockedByOtherThread() { - return null != owner && Thread.currentThread() != owner ; + public final boolean isOwner(Thread thread) { + synchronized(sdata) { + return sdata.owner == thread ; + } } - public synchronized int getRecursionCount() { - return recursionCount; + public final boolean isLocked() { + synchronized(sdata) { + return null != sdata.owner; + } } - public synchronized void validateLocked() { - if ( !isLocked() ) { - throw new RuntimeException(Thread.currentThread()+": Not locked"); + public final boolean isLockedByOtherThread() { + synchronized(sdata) { + return null != sdata.owner && Thread.currentThread() != sdata.owner ; } - if ( !isOwner() ) { - getLockedStack().printStackTrace(); - throw new RuntimeException(Thread.currentThread()+": Not owner, owner is "+owner); + } + + public final int getRecursionCount() { + synchronized(sdata) { + return sdata.recursionCount; } } - /** Recursive and blocking lockSurface() implementation */ - public synchronized void lock() { - Thread cur = Thread.currentThread(); - if(TRACE_LOCK) { - System.out.println("... LOCK 0 ["+this+"], recursions "+recursionCount+", "+cur); + public final void validateLocked() { + synchronized(sdata) { + if ( null == sdata.owner ) { + throw new RuntimeException(Thread.currentThread()+": Not locked"); + } + if ( Thread.currentThread() != sdata.owner ) { + getLockedStack().printStackTrace(); + throw new RuntimeException(Thread.currentThread()+": Not owner, owner is "+sdata.owner); + } } - if (owner == cur) { - ++recursionCount; + } + + /** Recursive and blocking lockSurface() implementation */ + public final void lock() { + synchronized(sdata) { + Thread cur = Thread.currentThread(); if(TRACE_LOCK) { - System.out.println("+++ LOCK 1 ["+this+"], recursions "+recursionCount+", "+cur); + System.out.println("... LOCK 0 ["+this+"], recursions "+sdata.recursionCount+", "+cur); + } + if (sdata.owner == cur) { + ++sdata.recursionCount; + if(TRACE_LOCK) { + System.out.println("+++ LOCK 1 ["+this+"], recursions "+sdata.recursionCount+", "+cur); + } + return; } - return; - } - long ts = System.currentTimeMillis(); - while (owner != null && (System.currentTimeMillis()-ts) < timeout) { - try { - wait(timeout); - } catch (InterruptedException e) { - throw new RuntimeException(e); + long ts = System.currentTimeMillis(); + while (sdata.owner != null && (System.currentTimeMillis()-ts) < timeout) { + try { + sdata.wait(timeout); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } + if(sdata.owner != null) { + sdata.lockedStack.printStackTrace(); + throw new RuntimeException("Waited "+timeout+"ms for: "+sdata.owner+" - "+cur+", with recursionCount "+sdata.recursionCount+", lock: "+this); + } + if(TRACE_LOCK) { + System.out.println("+++ LOCK X ["+this+"], recursions "+sdata.recursionCount+", "+cur); + } + sdata.owner = cur; + sdata.lockedStack = new Exception("Previously locked by "+sdata.owner+", lock: "+this); } - if(owner != null) { - lockedStack.printStackTrace(); - throw new RuntimeException("Waited "+timeout+"ms for: "+owner+" - "+cur+", with recursionCount "+recursionCount+", lock: "+this); - } - if(TRACE_LOCK) { - System.out.println("+++ LOCK X ["+this+"], recursions "+recursionCount+", "+cur); - } - owner = cur; - lockedStack = new Exception("Previously locked by "+owner+", lock: "+this); } /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlock() { + public final void unlock() { unlock(null); } /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlock(Runnable taskAfterUnlockBeforeNotify) { - validateLocked(); - - if (recursionCount > 0) { - --recursionCount; + public final void unlock(Runnable taskAfterUnlockBeforeNotify) { + synchronized(sdata) { + validateLocked(); + + if (sdata.recursionCount > 0) { + --sdata.recursionCount; + if(TRACE_LOCK) { + System.out.println("--- LOCK 1 ["+this+"], recursions "+sdata.recursionCount+", "+Thread.currentThread()); + } + return; + } + sdata.owner = null; + sdata.lockedStack = null; + if(null!=taskAfterUnlockBeforeNotify) { + taskAfterUnlockBeforeNotify.run(); + } if(TRACE_LOCK) { - System.out.println("--- LOCK 1 ["+this+"], recursions "+recursionCount+", "+Thread.currentThread()); + System.out.println("--- LOCK X ["+this+"], recursions "+sdata.recursionCount+", "+Thread.currentThread()); } - return; - } - owner = null; - lockedStack = null; - if(null!=taskAfterUnlockBeforeNotify) { - taskAfterUnlockBeforeNotify.run(); - } - if(TRACE_LOCK) { - System.out.println("--- LOCK X ["+this+"], recursions "+recursionCount+", "+Thread.currentThread()); + // Assuming notify() implementation weaks up the longest waiting thread, to avoid starvation. + // Otherwise we would need to have a Thread queue implemented, using sleep(timeout) and interrupt. + sdata.notify(); } - notifyAll(); } } |