2006-06-13 Maciej Piechotka [EMAIL PROTECTED]
* java/util/concurrent/lock/* : Add java.util.concurrent.locks patches
diff -ruN java.old/util/concurrent/locks/AbstractQueuedSynchronizer.java java/util/concurrent/locks/AbstractQueuedSynchronizer.java
--- java.old/util/concurrent/locks/AbstractQueuedSynchronizer.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/AbstractQueuedSynchronizer.java 2006-06-13 11:29:42.000000000 +0200
@@ -0,0 +1,352 @@
+package java.util.concurrent.locks;
+
+import java.io.Serializable;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+public abstract class AbstractQueuedSynchronizer implements Serializable
+{
+ public class ConditionObject implements Condition, Serializable
+ {
+ public ConditionObject()
+ {
+ owned.add(this);
+ }
+ public final synchronized void signal()
+ {
+ Thread toSignal = waitings.poll();
+ if(toSignal == null)
+ signaled.add(toSignal);
+ }
+ public final synchronized void signalAll()
+ {
+ signaled.addAll(waitings);
+ waitings.clear();
+ }
+ public final void awaitUninterruptibly()
+ {
+ Thread t = Thread.currentThread();
+ int state = prepareAwait(t);
+ while(!isSignaled(t))
+ Thread.yield();
+ finalizeAwait(state, t);
+ }
+ public final void await() throws InterruptedException
+ {
+ checkInterrups();
+ Thread t = Thread.currentThread();
+ int state = prepareAwait(t);
+ while(!isSignaled(t))
+ {
+ Thread.yield();
+ checkInterrups();
+ }
+ finalizeAwait(state, t);
+ }
+ public final long awaitNanos(long nanosTimeout) throws InterruptedException
+ {
+ checkInterrups();
+ final long end = System.nanoTime() + nanosTimeout;
+ Thread t = Thread.currentThread();
+ int state = prepareAwait(t);
+ while(!isSignaled(t))
+ {
+ if(end > System.nanoTime())
+ return 0;
+ Thread.yield();
+ checkInterrups();
+ }
+ /* I don't know how implement it.
+ In specyfication is written:
+ Returns:
+ A value less than or equal to zero if the wait has timed out; otherwise an estimate, that is strictly less than the nanosTimeout argument, of the time still remaining when this method returned.
+ But what if thread is yield between check of time and acquire?
+ It'd have to be something like Big Kernel Lock :(
+ */
+ return finalizeAwait(state, t);
+ }
+ public final boolean awaitUntil(Date deadline) throws InterruptedException
+ {
+ checkInterrups();
+ Thread t = Thread.currentThread();
+ int state = prepareAwait(t);
+ while(!isSignaled(t))
+ {
+ if(new Date().compareTo(deadline) > 1)
+ return false;
+ Thread.yield();
+ checkInterrups();
+ }
+ finalizeAwait(state, t);
+ return true;
+ }
+ public final boolean await(long time, TimeUnit unit)
+ throws InterruptedException
+ {
+ /* It's the simplest way I've found. Correct for less then 300 years */
+ return awaitNanos(unit.toNanos(time)) > 0;
+ }
+ protected final boolean hasWaiters()
+ {
+ if(isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ return !queue.isEmpty();
+ }
+ protected final int getWaitQueueLength()
+ {
+ if(isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ return queue.size();
+ }
+ protected final Collection<Thread> getWaitingThreads()
+ {
+ if(isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ /* Should be waitings returned or clone? */
+ return new LinkedList<Thread>(waitings);
+ }
+ private final synchronized int prepareAwait(Thread t)
+ {
+ int state = getState();
+ if(!release(state))
+ throw new IllegalMonitorStateException();
+ waitings.offer(t);
+ return state;
+ }
+ private final synchronized long finalizeAwait(int state, Thread t)
+ {
+ final long time = System.nanoTime();
+ acquire(state);
+ signaled.remove(t);
+ return time;
+ }
+ private final boolean isSignaled(Thread t)
+ {
+ return signaled.contains(t);
+ }
+ private Queue<Thread> waitings = new LinkedList<Thread>();
+ private Set<Thread> signaled = new HashSet<Thread>();
+ }
+
+ protected final int getState()
+ {
+ return state;
+ }
+ protected final void setState(int newState)
+ {
+ state = newState;
+ }
+ protected final synchronized boolean compareAndSetState(int expect,
+ int update)
+ {
+ if(state == expect)
+ {
+ state = update;
+ return true;
+ }
+ else
+ return false;
+ }
+ protected boolean tryAcquire(int arg)
+ {
+ throw new UnsupportedOperationException();
+ }
+ private synchronized boolean tryAcquire(int arg, Thread t)
+ {
+ if(tryAcquire(arg))
+ {
+ queue.remove(t);
+ exclusive.remove(t);
+ return true;
+ }
+ else if(!exclusive.contains(t))
+ {
+ contended = true;
+ queue.add(t);
+ exclusive.add(t);
+ }
+ return false;
+ }
+ protected boolean tryRelease(int arg)
+ {
+ throw new UnsupportedOperationException();
+ }
+ protected boolean tryAcquireShared(int arg)
+ {
+ throw new UnsupportedOperationException();
+ }
+ private synchronized boolean tryAcquireShared(int arg, Thread t)
+ {
+ if(tryAcquire(arg))
+ {
+ queue.remove(t);
+ shared.remove(t);
+ return true;
+ }
+ else if(!exclusive.contains(t))
+ {
+ queue.remove(t);
+ shared.remove(t);
+ }
+ return false;
+ }
+ protected boolean tryReleaseShared(int arg)
+ {
+ throw new UnsupportedOperationException();
+ }
+ protected boolean isHeldExclusively()
+ {
+ throw new UnsupportedOperationException();
+ }
+ public final void acquire(int arg)
+ {
+ Thread t = Thread.currentThread();
+ while(!tryAcquire(arg, t))
+ Thread.yield();
+ }
+ public final void acquireInterruptibly(int arg) throws InterruptedException
+ {
+ Thread t = Thread.currentThread();
+ checkInterrups();
+ while(!tryAcquire(arg, t))
+ {
+ Thread.yield();
+ checkInterrups();
+ }
+ }
+ public final boolean tryAcquireNanos(int arg, long nanosTimeout)
+ throws InterruptedException
+ {
+ Thread t = Thread.currentThread();
+ final long end = System.nanoTime() + nanosTimeout;
+ checkInterrups();
+ while(!tryAcquire(arg, t))
+ {
+ if(end > System.nanoTime())
+ return false;
+ Thread.yield();
+ checkInterrups();
+ }
+ return true;
+ }
+ public final boolean release(int arg)
+ {
+ return tryRelease(arg);
+ }
+ public final void acquireShared(int arg)
+ {
+ Thread t = Thread.currentThread();
+ while(!tryAcquireShared(arg, t))
+ Thread.yield();
+ }
+ public final void acquireSharedInterruptibly(int arg)
+ throws InterruptedException
+ {
+ Thread t = Thread.currentThread();
+ checkInterrups();
+ while(!tryAcquireShared(arg, t))
+ {
+ Thread.yield();
+ checkInterrups();
+ }
+ }
+ public final boolean tryAcquirSharedeNanos(int arg, long nanosTimeout)
+ throws InterruptedException
+ {
+ Thread t = Thread.currentThread();
+ final long end = System.nanoTime() + nanosTimeout;
+ checkInterrups();
+ while(!tryAcquireShared(arg, t))
+ {
+ if(end < System.nanoTime())
+ return false;
+ Thread.yield();
+ checkInterrups();
+ }
+ return true;
+ }
+ public final boolean releaseShared(int arg)
+ {
+ return tryReleaseShared(arg);
+ }
+ public final boolean hasQueuedThreads()
+ {
+ return queue.isEmpty();
+ }
+ public final boolean hasContended()
+ {
+ /* I'm not sure I understend documentation */
+ return contended;
+ }
+ public final synchronized Thread getFirstQueuedThread()
+ {
+ Iterator<Thread> i = queue.iterator();
+ if(i.hasNext())
+ return i.next();
+ else
+ return null;
+ }
+ public final boolean isQueued(Thread thread)
+ {
+ if(thread == null)
+ throw new NullPointerException();
+ return queue.contains(thread);
+ }
+ public final int getQueueLength()
+ {
+ return queue.size();
+ }
+ public final Collection<Thread> getQueuedThreads()
+ {
+ return new HashSet<Thread>(queue);
+ }
+ public final Collection<Thread> getExclusiveQueuedThreads()
+ {
+ return new HashSet<Thread>(exclusive);
+ }
+ public final Collection<Thread> getSharedQueuedThreads()
+ {
+ return new HashSet<Thread>(shared);
+ }
+ public String toString()
+ {
+ return "state=" + state;
+ }
+ public final boolean owns(ConditionObject condition)
+ {
+ if(condition == null)
+ throw new NullPointerException();
+ return owned.contains(condition);
+ }
+ public final boolean hasWaiters(ConditionObject condition)
+ {
+ return condition.hasWaiters();
+ }
+ public final int getWaitQueueLength(ConditionObject condition)
+ {
+ return condition.getWaitQueueLength();
+ }
+ public final Collection<Thread> getWaitingThreads(ConditionObject condition)
+ {
+ return condition.getWaitingThreads();
+ }
+ private void checkInterrups() throws InterruptedException
+ {
+ if(Thread.interrupted())
+ throw new InterruptedException();
+ }
+ private int state = 0;
+ private boolean contended = false;
+ private Queue<Thread> queue = new LinkedList<Thread>();
+ private Queue<Thread> exclusive = new LinkedList<Thread>();
+ private Queue<Thread> shared = new LinkedList<Thread>();
+ private Set<ConditionObject> owned = new HashSet<ConditionObject>();
+}
+
diff -ruN java.old/util/concurrent/locks/Condition.java java/util/concurrent/locks/Condition.java
--- java.old/util/concurrent/locks/Condition.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/Condition.java 2006-06-13 11:32:02.000000000 +0200
@@ -0,0 +1,21 @@
+package java.util.concurrent.locks;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+public interface Condition
+{
+ void await() throws InterruptedException;
+
+ void awaitUninterruptibly();
+
+ long awaitNanos(long nanosTimeout) throws InterruptedException;
+
+ boolean await(long time, TimeUnit unit) throws InterruptedException;
+
+ boolean awaitUntil(Date deadline) throws InterruptedException;
+
+ void signal();
+
+ void signalAll();
+}
diff -ruN java.old/util/concurrent/locks/Lock.java java/util/concurrent/locks/Lock.java
--- java.old/util/concurrent/locks/Lock.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/Lock.java 2006-06-13 11:32:12.000000000 +0200
@@ -0,0 +1,14 @@
+package java.util.concurrent.locks;
+
+import java.util.concurrent.TimeUnit;
+
+public interface Lock
+{
+ void lock();
+ void lockInterruptibly() throws InterruptedException;
+ boolean tryLock();
+ boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
+ void unlock();
+ Condition newCondition();
+}
+
diff -ruN java.old/util/concurrent/locks/ReadWriteLock.java java/util/concurrent/locks/ReadWriteLock.java
--- java.old/util/concurrent/locks/ReadWriteLock.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/ReadWriteLock.java 2006-06-13 11:31:52.000000000 +0200
@@ -0,0 +1,7 @@
+package java.util.concurrent.locks;
+
+public interface ReadWriteLock
+{
+ Lock readLock();
+ Lock writeLock();
+}
diff -ruN java.old/util/concurrent/locks/LockSupport.java java/util/concurrent/locks/LockSupport.java
--- java.old/util/concurrent/locks/LockSupport.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/LockSupport.java 2006-06-12 21:27:36.000000000 +0200
@@ -0,0 +1,76 @@
+package java.util.concurrent.locks;
+
+import java.util.concurrent.TimeUnit;
+
+public class LockSupport
+{
+ public static void unpark(Thread thread)
+ {
+ /* if(threadLocks.contains(thread)) {
+ * threadLocks.get(thread).notify();
+ * threadLocks.remove(thread);
+ * } */
+ synchronized(thread)
+ {
+ thread.notify();
+ }
+ }
+
+ public static void park()
+ {
+ /* Is method depended on threads is safe?
+ * It could be also used with some set/map
+ * (in comments) which get more of CPU
+ * And all methods should be synchonised */
+ Thread thread = Thread.currentThread();
+ synchronized (thread)
+ {
+ try
+ {
+ /* threadLocks.put(thread, new Boolean(true)).wait(); */
+ thread.wait();
+ }
+ catch (InterruptedException e)
+ {
+ // Just ignore
+ }
+ }
+ }
+ public static void parkNanos(long nanos)
+ {
+ Thread thread = Thread.currentThread();
+ synchronized (thread)
+ {
+ try
+ {
+ /* TimeUnit.NANOSECONDS.timedWait(threadsLocks.put(thread,
+ * new Boolean(true)),
+ * deadline); */
+ TimeUnit.NANOSECONDS.timedWait(thread, nanos);
+ }
+ catch (InterruptedException e)
+ {
+ // Just ignore
+ }
+ }
+ }
+ public static void parkUntil(long deadline)
+ {
+ Thread thread = Thread.currentThread();
+ synchronized (thread)
+ {
+ try
+ {
+ /* TimeUnit.MILLISECONDS.timedWait(threadsLocks.put(thread,
+ * new Boolean(true)),
+ * deadline); */
+ TimeUnit.MILLISECONDS.timedWait(thread, deadline);
+ }
+ catch (InterruptedException e)
+ {
+ // Just ignore
+ }
+ }
+ }
+ /* private static Map<Thread, Object> threadsLocks; */
+}
diff -ruN java.old/util/concurrent/locks/ReentrantLock.java java/util/concurrent/locks/ReentrantLock.java
--- java.old/util/concurrent/locks/ReentrantLock.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/ReentrantLock.java 2006-06-13 11:33:20.000000000 +0200
@@ -0,0 +1,187 @@
+
+
+package java.util.concurrent.locks;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
+
+public class ReentrantLock
+ implements Lock, Serializable
+{
+ private class Sync
+ extends AbstractQueuedSynchronizer
+ {
+ public Sync(boolean fair)
+ {
+ this.fair = fair;
+ }
+ @Override
+ protected boolean isHeldExclusively()
+ {
+ return isLocked();
+ }
+ @Override
+ public synchronized boolean tryAcquire(int arg)
+ {
+ if (isHeldByCurrentThread())
+ {
+ if(getState() == Integer.MAX_VALUE)
+ /* Anybody knows which error? */
+ throw new Error();
+ setState(getState() + 1);
+ return true;
+ }
+ else
+ {
+ if (! isLocked())
+ return false;
+ Thread thread = Thread.currentThread();
+ if (! fair || thread == getFirstQueuedThread())
+ {
+ setState(1);
+ holdingThread = thread;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+ @Override
+ public synchronized boolean tryRelease(int arg)
+ {
+ if (! isHeldByCurrentThread())
+ throw new IllegalMonitorStateException();
+ setState(getState() - 1);
+ if (getState() == 0)
+ holdingThread = null;
+ return ! isHeldExclusively();
+ }
+
+ protected Condition newCondition()
+ {
+ return new ConditionObject();
+ }
+ private Thread holdingThread = null;
+ private boolean fair;
+ }
+ public ReentrantLock()
+ {
+ this(false);
+ }
+ public ReentrantLock(boolean fair)
+ {
+ this.sync = new Sync(fair);
+ }
+ public void lock()
+ {
+ sync.acquire(1);
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ sync.acquireInterruptibly(1);
+ }
+
+ public boolean tryLock()
+ {
+ return sync.tryAcquire(1);
+ }
+
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException
+ {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ public void unlock()
+ {
+ sync.release(1);
+ }
+
+ public Condition newCondition()
+ {
+ return sync.newCondition();
+ }
+
+ public int getHoldCount()
+ {
+ return sync.getState();
+ }
+
+ public boolean isHeldByCurrentThread()
+ {
+ return sync.holdingThread == Thread.currentThread();
+ }
+
+ public boolean isLocked()
+ {
+ return sync.holdingThread != null;
+ }
+
+ public final boolean isFair()
+ {
+ return sync.fair;
+ }
+
+ protected Thread getOwner()
+ {
+ return sync.holdingThread;
+ }
+
+ public final boolean hasQueuedThreads()
+ {
+ return sync.hasQueuedThreads();
+ }
+
+ public final boolean hasQueuedThread(Thread thread)
+ {
+ return sync.isQueued(thread);
+ }
+
+ public final int getQueueLength()
+ {
+ return sync.getQueueLength();
+ }
+
+ protected Collection<Thread> getQueuedThreads()
+ {
+ return sync.getQueuedThreads();
+ }
+
+ public boolean hasWaiters(Condition condition)
+ {
+ return sync.hasWaiters(cast(condition));
+ }
+
+ public int getWaitQueueLength(Condition condition)
+ {
+ return sync.getWaitQueueLength(cast(condition));
+ }
+
+ protected Collection<Thread> getWaitingThreads(Condition condition)
+ {
+ return sync.getWaitingThreads(cast(condition));
+ }
+
+ public synchronized String toString()
+ {
+ return isLocked() ? "Locked by" + sync.holdingThread.getName() : "Unlocked";
+ }
+
+ private ConditionObject cast(Condition condition)
+ {
+ if (condition instanceof ConditionObject)
+ {
+ ConditionObject object = (ConditionObject) condition;
+ if (sync.owns(object))
+ return object;
+ }
+ throw new IllegalArgumentException();
+ }
+
+ private Sync sync;
+}
diff -ruN java.old/util/concurrent/locks/ReentrantReadWriteLock.java java/util/concurrent/locks/ReentrantReadWriteLock.java
--- java.old/util/concurrent/locks/ReentrantReadWriteLock.java 1970-01-01 01:00:00.000000000 +0100
+++ java/util/concurrent/locks/ReentrantReadWriteLock.java 2006-06-13 11:33:20.000000000 +0200
@@ -0,0 +1,324 @@
+
+
+package java.util.concurrent.locks;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject;
+
+public class ReentrantReadWriteLock implements ReadWriteLock
+{
+ private class Sync
+ extends AbstractQueuedSynchronizer
+ {
+ @Override
+ public boolean isHeldExclusively()
+ {
+ return getState() > 1;
+ }
+
+ @Override
+ public synchronized boolean tryAcquire(int arg)
+ {
+ Thread thread = Thread.currentThread();
+ if (thread == holdingThread)
+ {
+ if (getState() == Integer.MAX_VALUE)
+ /* Anybody knows which error? */
+ throw new Error();
+ holds++;
+ return true;
+ }
+ else if (getState() > 0)
+ {
+ return false;
+ }
+ else
+ {
+ setState(2);
+ holdingThread = thread;
+ return true;
+ }
+ }
+
+ @Override
+ public synchronized boolean tryRelease(int arg)
+ {
+ if (holdingThread == Thread.currentThread())
+ throw new IllegalMonitorStateException();
+ if (--holds == 0)
+ {
+ holdingThread = null;
+ setState(0);
+ }
+ return ! isHeldExclusively();
+ }
+
+ @Override
+ public synchronized boolean tryAcquireShared(int arg)
+ {
+ Thread thread = Thread.currentThread();
+ switch(getState())
+ {
+ case 0:
+ if(fair && thread != getFirstQueuedThread())
+ return false;
+ setState(1);
+ shared = 1;
+ return true;
+ case 1:
+ if(fair && thread != getFirstQueuedThread())
+ return false;
+ shared++;
+ return true;
+ default:
+ if(thread != holdingThread)
+ return false;
+ shared++;
+ return true;
+ }
+ }
+
+ @Override
+ public synchronized boolean tryReleaseShared(int arg)
+ {
+ if(shared > 0)
+ shared--;
+ return shared == 0;
+ }
+
+ protected Condition newCondition()
+ {
+ return new ConditionObject();
+ }
+
+ private int shared = 0;
+ private int holds = 0;
+ private Thread holdingThread;
+
+ private boolean fair;
+ }
+
+ public static class ReadLock
+ implements Lock, Serializable
+ {
+ protected ReadLock(ReentrantReadWriteLock lock)
+ {
+ sync = lock.sync;
+ }
+
+ public void lock()
+ {
+ sync.acquireShared(1);
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ sync.acquireInterruptibly(1);
+ }
+
+ public boolean tryLock()
+ {
+ return sync.tryAcquireShared(1);
+ }
+
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException
+ {
+ return sync.tryAcquireNanos(1, unit.toNanos(timeout));
+ }
+
+ public void unlock()
+ {
+ sync.releaseShared(1);
+ }
+
+ public Condition newCondition()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public String toString()
+ {
+ return "Read locks=" + sync.shared;
+ }
+
+ private Sync sync;
+ }
+
+ public static class WriteLock
+ implements Lock, Serializable
+ {
+ WriteLock(ReentrantReadWriteLock lock)
+ {
+ sync = lock.sync;
+ }
+
+ public void lock()
+ {
+ sync.acquire(2);
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ sync.acquireInterruptibly(2);
+ }
+
+ public boolean tryLock()
+ {
+ return sync.tryAcquire(2);
+ }
+
+ public boolean tryLock(long timeout, TimeUnit unit)
+ throws InterruptedException
+ {
+ return sync.tryAcquireNanos(2, unit.toNanos(timeout));
+ }
+
+ public void unlock()
+ {
+ sync.release(2);
+ }
+
+ public Condition newCondition()
+ {
+ return sync.newCondition();
+ }
+
+ public synchronized String toString()
+ {
+ return sync.holdingThread == null ? "Locked by"
+ + sync.holdingThread.getName()
+ : "Unlocked";
+ }
+
+ private Sync sync;
+ }
+
+ public ReentrantReadWriteLock()
+ {
+ this(false);
+ }
+
+ public ReentrantReadWriteLock(boolean fair)
+ {
+ this.sync.fair = fair;
+ }
+
+ public Lock readLock()
+ {
+ return readLock;
+ }
+
+ public Lock writeLock()
+ {
+ return writeLock;
+ }
+
+ public final boolean isFair()
+ {
+ return sync.fair;
+ }
+
+ protected Thread getOwner()
+ {
+ return sync.holdingThread;
+ }
+
+ public int getReadLockCount()
+ {
+ return sync.shared;
+ }
+
+ public boolean isWriteLocked()
+ {
+ return sync.holdingThread != null;
+ }
+
+ public boolean isWriteLockedByCurrentThread()
+ {
+ return sync.holdingThread == Thread.currentThread();
+ }
+
+ public int getWriteHoldCount()
+ {
+ int hold = sync.getState() - 1;
+ return hold < 0 ? 0 : hold;
+ }
+
+ protected Collection<Thread> getQueuedWriterThreads()
+ {
+ return sync.getExclusiveQueuedThreads();
+ }
+
+ protected Collection<Thread> getQueuedReaderThreads()
+ {
+ return sync.getSharedQueuedThreads();
+ }
+
+ public final boolean hasQueuedThreads()
+ {
+ return sync.hasQueuedThreads();
+ }
+
+ public final boolean hasQueuedThread(Thread thread)
+ {
+ return sync.hasQueuedThreads();
+ }
+
+ public final int getQueueLength()
+ {
+ return sync.getQueueLength();
+ }
+
+ protected Collection<Thread> getQueuedThreads()
+ {
+ return sync.getQueuedThreads();
+ }
+
+ public boolean hasWaiters(Condition condition)
+ {
+ return sync.hasWaiters(cast(condition));
+ }
+
+ public int getWaitQueueLength(Condition condition)
+ {
+ return sync.getWaitQueueLength(cast(condition));
+ }
+
+ protected Collection<Thread> getWaitingThreads(Condition condition)
+ {
+ return sync.getWaitingThreads(cast(condition));
+ }
+
+ public synchronized String toString()
+ {
+ switch (sync.getState())
+ {
+ case 0:
+ return "Unlocked";
+ case 1:
+ return "Read locks = " + sync.shared;
+ default:
+ return "Write locks = " + getWriteHoldCount();
+ }
+ }
+
+ private ConditionObject cast(Condition condition)
+ {
+ if (condition instanceof ConditionObject)
+ {
+ ConditionObject object = (ConditionObject) condition;
+ if (sync.owns(object))
+ return object;
+ }
+ throw new IllegalArgumentException();
+ }
+
+ private Lock readLock = new ReadLock(this);
+
+ private Lock writeLock = new WriteLock(this);
+
+ private Sync sync;
+}