/** * 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.List; import java.util.concurrent.locks.AbstractOwnableSynchronizer; import com.jogamp.common.util.locks.RecursiveLock; /** * Reentrance locking toolkit, impl a non-complete fair FIFO scheduler. *
* Fair scheduling is not guaranteed due to the usage of {@link Object#notify()}, * however new lock-applicants will wait if queue is not empty for {@link #lock()} * and {@link #tryLock(long) tryLock}(timeout>0).
* ** Sync object extends {@link AbstractOwnableSynchronizer}, hence monitoring is possible.
*/ public class RecursiveLockImpl01Unfairish implements RecursiveLock { /* package */ static interface Sync { Thread getOwner(); boolean isOwner(Thread t); void setOwner(Thread t); Throwable getLockedStack(); void setLockedStack(Throwable s); int getHoldCount(); void incrHoldCount(Thread t); void decrHoldCount(Thread t); int getQSz(); void incrQSz(); void decrQSz(); } @SuppressWarnings("serial") /* package */ static class SingleThreadSync extends AbstractOwnableSynchronizer implements Sync { /* package */ SingleThreadSync() { super(); } @Override public final Thread getOwner() { return getExclusiveOwnerThread(); } @Override public boolean isOwner(final Thread t) { return getExclusiveOwnerThread()==t; } @Override public final void setOwner(final Thread t) { setExclusiveOwnerThread(t); } @Override public final Throwable getLockedStack() { return lockedStack; } @Override public final void setLockedStack(final Throwable s) { final Listnull
.
* @see com.jogamp.common.util.locks.Lock#DEBUG
*/
public final Throwable getLockedStack() {
synchronized(sync) {
return sync.getLockedStack();
}
}
@Override
public final Thread getOwner() {
synchronized(sync) {
return sync.getOwner();
}
}
@Override
public final boolean isOwner(final Thread thread) {
synchronized(sync) {
return sync.isOwner(thread);
}
}
@Override
public final boolean isLocked() {
synchronized(sync) {
return null != sync.getOwner();
}
}
@Override
public final boolean isLockedByOtherThread() {
synchronized(sync) {
final Thread o = sync.getOwner();
return null != o && Thread.currentThread() != o ;
}
}
@Override
public final int getHoldCount() {
synchronized(sync) {
return sync.getHoldCount();
}
}
@Override
public final void validateLocked() throws RuntimeException {
synchronized(sync) {
if ( !sync.isOwner(Thread.currentThread()) ) {
if ( null == sync.getOwner() ) {
throw new RuntimeException(threadName(Thread.currentThread())+": Not locked: "+toString());
}
if(null!=sync.getLockedStack()) {
sync.getLockedStack().printStackTrace();
}
throw new RuntimeException(Thread.currentThread()+": Not owner: "+toString());
}
}
}
@Override
public final void lock() {
synchronized(sync) {
try {
if(!tryLock(TIMEOUT)) {
if(null!=sync.getLockedStack()) {
sync.getLockedStack().printStackTrace();
}
throw new RuntimeException("Waited "+TIMEOUT+"ms for: "+toString()+" - "+threadName(Thread.currentThread()));
}
} catch (final InterruptedException e) {
throw new RuntimeException("Interrupted", e);
}
}
}
@Override
public final boolean tryLock(long timeout) throws InterruptedException {
synchronized(sync) {
final Thread cur = Thread.currentThread();
if(TRACE_LOCK) {
System.err.println("+++ LOCK 0 "+toString()+", timeout "+timeout+" ms, cur "+threadName(cur));
}
if (sync.isOwner(cur)) {
sync.incrHoldCount(cur);
if(TRACE_LOCK) {
System.err.println("+++ LOCK XR "+toString()+", cur "+threadName(cur));
}
return true;
}
if ( sync.getOwner() != null || ( 0