/** * 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 jogamp.common.util.locks; import java.util.ArrayList; import java.util.List; import java.util.concurrent.locks.AbstractOwnableSynchronizer; import com.jogamp.common.util.locks.RecursiveLock; /** * Reentrance locking toolkit, impl a complete fair FIFO scheduler * *
* Sync object extends {@link AbstractOwnableSynchronizer}, hence monitoring is possible.
*/ public class RecursiveLockImpl01CompleteFair implements RecursiveLock { private static class WaitingThread { WaitingThread(Thread t) { thread = t; signaledByUnlock = false; } final Thread thread; boolean signaledByUnlock; // if true, it's also removed from queue } @SuppressWarnings("serial") private static class Sync extends AbstractOwnableSynchronizer { private Sync() { super(); } private final Thread getOwner() { return getExclusiveOwnerThread(); } private final void setOwner(Thread t) { setExclusiveOwnerThread(t); } private final void setLockedStack(Throwable s) { Listnull
.
* @see com.jogamp.common.util.locks.Lock#DEBUG
*/
public final Throwable getLockedStack() {
synchronized(sync) {
return sync.lockedStack;
}
}
public final Thread getOwner() {
synchronized(sync) {
return sync.getOwner();
}
}
public final boolean isOwner() {
synchronized(sync) {
return isOwner(Thread.currentThread());
}
}
public final boolean isOwner(Thread thread) {
synchronized(sync) {
return sync.getOwner() == thread ;
}
}
public final boolean isLocked() {
synchronized(sync) {
return null != sync.getOwner();
}
}
public final boolean isLockedByOtherThread() {
synchronized(sync) {
return null != sync.getOwner() && Thread.currentThread() != sync.getOwner() ;
}
}
public final int getHoldCount() {
synchronized(sync) {
return sync.holdCount;
}
}
public final void validateLocked() throws RuntimeException {
synchronized(sync) {
if ( Thread.currentThread() != sync.getOwner() ) {
if ( null == sync.getOwner() ) {
throw new RuntimeException(threadName(Thread.currentThread())+": Not locked: "+toString());
}
if(null!=sync.lockedStack) {
sync.lockedStack.printStackTrace();
}
throw new RuntimeException(Thread.currentThread()+": Not owner: "+toString());
}
}
}
public final void lock() {
synchronized(sync) {
try {
if(!tryLock(TIMEOUT)) {
if(null!=sync.lockedStack) {
sync.lockedStack.printStackTrace();
}
throw new RuntimeException("Waited "+TIMEOUT+"ms for: "+toString()+" - "+threadName(Thread.currentThread()));
}
} catch (InterruptedException e) {
throw new RuntimeException("Interrupted", e);
}
}
}
public final boolean tryLock(long timeout) throws InterruptedException {
synchronized(sync) {
final Thread cur = Thread.currentThread();
if(TRACE_LOCK) {
System.err.println("+++ LOCK 0 "+toString()+", cur "+threadName(cur));
}
if (sync.getOwner() == cur) {
++sync.holdCount;
if(TRACE_LOCK) {
System.err.println("+++ LOCK XR "+toString()+", cur "+threadName(cur));
}
return true;
}
if ( sync.getOwner() != null || ( 0