summaryrefslogtreecommitdiff
path: root/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java')
-rw-r--r--src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java1341
1 files changed, 0 insertions, 1341 deletions
diff --git a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java b/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
deleted file mode 100644
index 914d242100..0000000000
--- a/src/actors/scala/actors/threadpool/locks/ReentrantReadWriteLock.java
+++ /dev/null
@@ -1,1341 +0,0 @@
-/*
- * Written by Doug Lea with assistance from members of JCP JSR-166
- * Expert Group and released to the public domain, as explained at
- * http://creativecommons.org/licenses/publicdomain
- */
-
-package scala.actors.threadpool.locks;
-
-import java.util.HashMap;
-import scala.actors.threadpool.*;
-import scala.actors.threadpool.helpers.*;
-
-/**
- * An implementation of {@link ReadWriteLock} supporting similar
- * semantics to {@link ReentrantLock}.
- * <p>This class has the following properties:
- *
- * <ul>
- * <li><b>Acquisition order</b>
- *
- * <p>The order of entry
- * to the read and write lock is unspecified, subject to reentrancy
- * constraints. A nonfair lock that is continuously contended may
- * indefinitely postpone one or more reader or writer threads, but
- * will normally have higher throughput than a fair lock.
- * <p>
- *
- * DEPARTURE FROM java.util.concurrent: this implementation impose
- * a writer-preference and thus its acquisition order may be different
- * than in java.util.concurrent.
- *
- * <li><b>Reentrancy</b>
- *
- * <p>This lock allows both readers and writers to reacquire read or
- * write locks in the style of a {@link ReentrantLock}. Non-reentrant
- * readers are not allowed until all write locks held by the writing
- * thread have been released.
- *
- * <p>Additionally, a writer can acquire the read lock, but not
- * vice-versa. Among other applications, reentrancy can be useful
- * when write locks are held during calls or callbacks to methods that
- * perform reads under read locks. If a reader tries to acquire the
- * write lock it will never succeed.
- *
- * <li><b>Lock downgrading</b>
- * <p>Reentrancy also allows downgrading from the write lock to a read lock,
- * by acquiring the write lock, then the read lock and then releasing the
- * write lock. However, upgrading from a read lock to the write lock is
- * <b>not</b> possible.
- *
- * <li><b>Interruption of lock acquisition</b>
- * <p>The read lock and write lock both support interruption during lock
- * acquisition.
- *
- * <li><b>{@link Condition} support</b>
- * <p>The write lock provides a {@link Condition} implementation that
- * behaves in the same way, with respect to the write lock, as the
- * {@link Condition} implementation provided by
- * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
- * This {@link Condition} can, of course, only be used with the write lock.
- *
- * <p>The read lock does not support a {@link Condition} and
- * {@code readLock().newCondition()} throws
- * {@code UnsupportedOperationException}.
- *
- * <li><b>Instrumentation</b>
- * <p>This class supports methods to determine whether locks
- * are held or contended. These methods are designed for monitoring
- * system state, not for synchronization control.
- * </ul>
- *
- * <p>Serialization of this class behaves in the same way as built-in
- * locks: a deserialized lock is in the unlocked state, regardless of
- * its state when serialized.
- *
- * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
- * reentrancy to perform lock downgrading after updating a cache (exception
- * handling is elided for simplicity):
- * <pre>
- * class CachedData {
- * Object data;
- * volatile boolean cacheValid;
- * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- *
- * void processCachedData() {
- * rwl.readLock().lock();
- * if (!cacheValid) {
- * // Must release read lock before acquiring write lock
- * rwl.readLock().unlock();
- * rwl.writeLock().lock();
- * // Recheck state because another thread might have acquired
- * // write lock and changed state before we did.
- * if (!cacheValid) {
- * data = ...
- * cacheValid = true;
- * }
- * // Downgrade by acquiring read lock before releasing write lock
- * rwl.readLock().lock();
- * rwl.writeLock().unlock(); // Unlock write, still hold read
- * }
- *
- * use(data);
- * rwl.readLock().unlock();
- * }
- * }
- * </pre>
- *
- * ReentrantReadWriteLocks can be used to improve concurrency in some
- * uses of some kinds of Collections. This is typically worthwhile
- * only when the collections are expected to be large, accessed by
- * more reader threads than writer threads, and entail operations with
- * overhead that outweighs synchronization overhead. For example, here
- * is a class using a TreeMap that is expected to be large and
- * concurrently accessed.
- *
- * <pre>{@code
- * class RWDictionary {
- * private final Map<String, Data> m = new TreeMap<String, Data>();
- * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- * private final Lock r = rwl.readLock();
- * private final Lock w = rwl.writeLock();
- *
- * public Data get(String key) {
- * r.lock();
- * try { return m.get(key); }
- * finally { r.unlock(); }
- * }
- * public String[] allKeys() {
- * r.lock();
- * try { return m.keySet().toArray(); }
- * finally { r.unlock(); }
- * }
- * public Data put(String key, Data value) {
- * w.lock();
- * try { return m.put(key, value); }
- * finally { w.unlock(); }
- * }
- * public void clear() {
- * w.lock();
- * try { m.clear(); }
- * finally { w.unlock(); }
- * }
- * }}</pre>
- *
- * <h3>Implementation Notes</h3>
- *
- * <p>This lock supports a maximum of 65535 recursive write locks
- * and 65535 read locks. Attempts to exceed these limits result in
- * {@link Error} throws from locking methods.
- *
- * @since 1.5
- * @author Doug Lea
- *
- */
-public class ReentrantReadWriteLock implements ReadWriteLock, java.io.Serializable {
- private static final long serialVersionUID = -3463448656717690166L;
-
- final ReadLock readerLock_ = new ReadLock(this);
- final WriteLock writerLock_ = new WriteLock(this);
-
- final Sync sync;
-
- /**
- * Creates a new {@code ReentrantReadWriteLock} with
- * default (nonfair) ordering properties.
- */
- public ReentrantReadWriteLock() {
- this.sync = new NonfairSync();
- }
-
- public Lock writeLock() { return writerLock_; }
- public Lock readLock() { return readerLock_; }
-
- /**
- * Synchronization implementation for ReentrantReadWriteLock.
- * Subclassed into fair and nonfair versions.
- */
- private abstract static class Sync implements java.io.Serializable {
-
- private static final int NONE = 0;
- private static final int READER = 1;
- private static final int WRITER = 2;
-
- transient int activeReaders_ = 0;
- transient Thread activeWriter_ = null;
- transient int waitingReaders_ = 0;
- transient int waitingWriters_ = 0;
-
- /** Number of acquires on write lock by activeWriter_ thread **/
- transient int writeHolds_ = 0;
-
- /** Number of acquires on read lock by any reader thread **/
- transient HashMap<Thread, Integer> readers_ = new HashMap<Thread, Integer>();
-
- /** cache/reuse the special Integer value one to speed up readlocks **/
- static final Integer IONE = new Integer(1);
-
- Sync() {}
-
- /*
- Each of these variants is needed to maintain atomicity
- of wait counts during wait loops. They could be
- made faster by manually inlining each other. We hope that
- compilers do this for us though.
- */
-
- synchronized boolean startReadFromNewReader() {
- boolean pass = startRead();
- if (!pass) ++waitingReaders_;
- return pass;
- }
-
- synchronized boolean startWriteFromNewWriter() {
- boolean pass = startWrite();
- if (!pass) ++waitingWriters_;
- return pass;
- }
-
- synchronized boolean startReadFromWaitingReader() {
- boolean pass = startRead();
- if (pass) --waitingReaders_;
- return pass;
- }
-
- synchronized boolean startWriteFromWaitingWriter() {
- boolean pass = startWrite();
- if (pass) --waitingWriters_;
- return pass;
- }
-
- /*
- A bunch of small synchronized methods are needed
- to allow communication from the Lock objects
- back to this object, that serves as controller
- */
-
- synchronized void cancelledWaitingReader() { --waitingReaders_; }
- synchronized void cancelledWaitingWriter() { --waitingWriters_; }
-
- boolean allowReader() {
- return (activeWriter_ == null && waitingWriters_ == 0) ||
- activeWriter_ == Thread.currentThread();
- }
-
- synchronized boolean startRead() {
- Thread t = Thread.currentThread();
- Object c = readers_.get(t);
- if (c != null) { // already held -- just increment hold count
- readers_.put(t, new Integer( ( (Integer) (c)).intValue() + 1));
- ++activeReaders_;
- return true;
- }
- else if (allowReader()) {
- readers_.put(t, IONE);
- ++activeReaders_;
- return true;
- }
- else
- return false;
- }
-
- synchronized boolean startWrite() {
- if (activeWriter_ == Thread.currentThread()) { // already held; re-acquire
- ++writeHolds_;
- return true;
- }
- else if (writeHolds_ == 0) {
- if (activeReaders_ == 0 ||
- (readers_.size() == 1 &&
- readers_.get(Thread.currentThread()) != null)) {
- activeWriter_ = Thread.currentThread();
- writeHolds_ = 1;
- return true;
- }
- else
- return false;
- }
- else
- return false;
- }
-
- synchronized int endRead() {
- Thread t = Thread.currentThread();
- Object c = readers_.get(t);
- if (c == null)
- throw new IllegalMonitorStateException();
- --activeReaders_;
- if (c != IONE) { // more than one hold; decrement count
- int h = ( (Integer) (c)).intValue() - 1;
- Integer ih = (h == 1) ? IONE : new Integer(h);
- readers_.put(t, ih);
- return NONE;
- }
- else {
- readers_.remove(t);
-
- if (writeHolds_ > 0) // a write lock is still held by current thread
- return NONE;
- else if (activeReaders_ == 0 && waitingWriters_ > 0)
- return WRITER;
- else
- return NONE;
- }
- }
-
- synchronized int endWrite() {
- if (activeWriter_ != Thread.currentThread()) {
- throw new IllegalMonitorStateException();
- }
- --writeHolds_;
- if (writeHolds_ > 0) // still being held
- return NONE;
- else {
- activeWriter_ = null;
- if (waitingReaders_ > 0 && allowReader())
- return READER;
- else if (waitingWriters_ > 0)
- return WRITER;
- else
- return NONE;
- }
- }
-
- synchronized Thread getOwner() {
- return activeWriter_;
- }
-
- synchronized int getReadLockCount() {
- return activeReaders_;
- }
-
- synchronized boolean isWriteLocked() {
- return activeWriter_ != null;
- }
-
- synchronized boolean isWriteLockedByCurrentThread() {
- return activeWriter_ == Thread.currentThread();
- }
-
- synchronized int getWriteHoldCount() {
- return isWriteLockedByCurrentThread() ? writeHolds_ : 0;
- }
-
- synchronized int getReadHoldCount() {
- if (activeReaders_ == 0) return 0;
- Thread t = Thread.currentThread();
- Integer i = readers_.get(t);
- return (i == null) ? 0 : i.intValue();
- }
-
- final synchronized boolean hasQueuedThreads() {
- return waitingWriters_ > 0 || waitingReaders_ > 0;
- }
-
- final synchronized int getQueueLength() {
- return waitingWriters_ + waitingReaders_;
- }
-
- private void readObject(java.io.ObjectInputStream in)
- throws java.io.IOException, ClassNotFoundException {
- in.defaultReadObject();
- // readers_ is transient, need to reinitialize. Let's flush the memory
- // and ensure visibility by synchronizing (all other accesses to
- // readers_ are also synchronized on "this")
- synchronized (this) {
- readers_ = new HashMap<Thread, Integer>();
- }
- }
- }
-
- /**
- * Nonfair version of Sync
- */
- private static class NonfairSync extends Sync {
- private static final long serialVersionUID = -2392241841540339773L;
-
- NonfairSync() {}
- }
-
- /**
- * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
- */
- public static class ReadLock implements Lock, java.io.Serializable {
-
- private static final long serialVersionUID = -5992448646407690164L;
-
- final ReentrantReadWriteLock lock;
-
- /**
- * Constructor for use by subclasses
- *
- * @param lock the outer lock object
- * @throws NullPointerException if the lock is null
- */
- protected ReadLock(ReentrantReadWriteLock lock) {
- if (lock == null) throw new NullPointerException();
- this.lock = lock;
- }
-
- /**
- * Acquires the read lock.
- *
- * <p>Acquires the read lock if the write lock is not held by
- * another thread and returns immediately.
- *
- * <p>If the write lock is held by another thread then
- * the current thread becomes disabled for thread scheduling
- * purposes and lies dormant until the read lock has been acquired.
- */
- public void lock() {
- synchronized (this) {
- if (lock.sync.startReadFromNewReader()) return;
- boolean wasInterrupted = Thread.interrupted();
- try {
- while (true) {
- try {
- ReadLock.this.wait();
- }
- catch (InterruptedException ex) {
- wasInterrupted = true;
- // no need to propagate the potentially masked
- // signal, since readers are always notified all
- }
- if (lock.sync.startReadFromWaitingReader()) return;
- }
- }
- finally {
- if (wasInterrupted) Thread.currentThread().interrupt();
- }
- }
- }
-
- /**
- * Acquires the read lock unless the current thread is
- * {@linkplain Thread#interrupt interrupted}.
- *
- * <p>Acquires the read lock if the write lock is not held
- * by another thread and returns immediately.
- *
- * <p>If the write lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
- * purposes and lies dormant until one of two things happens:
- *
- * <ul>
- *
- * <li>The read lock is acquired by the current thread; or
- *
- * <li>Some other thread {@linkplain Thread#interrupt interrupts}
- * the current thread.
- *
- * </ul>
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method; or
- *
- * <li>is {@linkplain Thread#interrupt interrupted} while
- * acquiring the read lock,
- *
- * </ul>
- *
- * then {@link InterruptedException} is thrown and the current
- * thread's interrupted status is cleared.
- *
- * <p>In this implementation, as this method is an explicit
- * interruption point, preference is given to responding to
- * the interrupt over normal or reentrant acquisition of the
- * lock.
- *
- * @throws InterruptedException if the current thread is interrupted
- */
- public void lockInterruptibly() throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- InterruptedException ie = null;
- synchronized (this) {
- if (!lock.sync.startReadFromNewReader()) {
- for (; ; ) {
- try {
- ReadLock.this.wait();
- if (lock.sync.startReadFromWaitingReader())
- return;
- }
- catch (InterruptedException ex) {
- lock.sync.cancelledWaitingReader();
- ie = ex;
- break;
- }
- }
- }
- }
- if (ie != null) {
- // fall through outside synch on interrupt.
- // This notification is not really needed here,
- // but may be in plausible subclasses
- lock.writerLock_.signalWaiters();
- throw ie;
- }
- }
-
- /**
- * Acquires the read lock only if the write lock is not held by
- * another thread at the time of invocation.
- *
- * <p>Acquires the read lock if the write lock is not held by
- * another thread and returns immediately with the value
- * {@code true}. Even when this lock has been set to use a
- * fair ordering policy, a call to {@code tryLock()}
- * <em>will</em> immediately acquire the read lock if it is
- * available, whether or not other threads are currently
- * waiting for the read lock. This &quot;barging&quot; behavior
- * can be useful in certain circumstances, even though it
- * breaks fairness. If you want to honor the fairness setting
- * for this lock, then use {@link #tryLock(long, TimeUnit)
- * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
- * (it also detects interruption).
- *
- * <p>If the write lock is held by another thread then
- * this method will return immediately with the value
- * {@code false}.
- *
- * @return {@code true} if the read lock was acquired
- */
- public boolean tryLock() {
- return lock.sync.startRead();
- }
-
- /**
- * Acquires the read lock if the write lock is not held by
- * another thread within the given waiting time and the
- * current thread has not been {@linkplain Thread#interrupt
- * interrupted}.
- *
- * <p>Acquires the read lock if the write lock is not held by
- * another thread and returns immediately with the value
- * {@code true}. If this lock has been set to use a fair
- * ordering policy then an available lock <em>will not</em> be
- * acquired if any other threads are waiting for the
- * lock. This is in contrast to the {@link #tryLock()}
- * method. If you want a timed {@code tryLock} that does
- * permit barging on a fair lock then combine the timed and
- * un-timed forms together:
- *
- * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
- * </pre>
- *
- * <p>If the write lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
- * purposes and lies dormant until one of three things happens:
- *
- * <ul>
- *
- * <li>The read lock is acquired by the current thread; or
- *
- * <li>Some other thread {@linkplain Thread#interrupt interrupts}
- * the current thread; or
- *
- * <li>The specified waiting time elapses.
- *
- * </ul>
- *
- * <p>If the read lock is acquired then the value {@code true} is
- * returned.
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method; or
- *
- * <li>is {@linkplain Thread#interrupt interrupted} while
- * acquiring the read lock,
- *
- * </ul> then {@link InterruptedException} is thrown and the
- * current thread's interrupted status is cleared.
- *
- * <p>If the specified waiting time elapses then the value
- * {@code false} is returned. If the time is less than or
- * equal to zero, the method will not wait at all.
- *
- * <p>In this implementation, as this method is an explicit
- * interruption point, preference is given to responding to
- * the interrupt over normal or reentrant acquisition of the
- * lock, and over reporting the elapse of the waiting time.
- *
- * @param timeout the time to wait for the read lock
- * @param unit the time unit of the timeout argument
- * @return {@code true} if the read lock was acquired
- * @throws InterruptedException if the current thread is interrupted
- * @throws NullPointerException if the time unit is null
- *
- */
- public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- InterruptedException ie = null;
- long nanos = unit.toNanos(timeout);
- synchronized (this) {
- if (nanos <= 0)
- return lock.sync.startRead();
- else if (lock.sync.startReadFromNewReader())
- return true;
- else {
- long deadline = Utils.nanoTime() + nanos;
- for (; ; ) {
- try {
- TimeUnit.NANOSECONDS.timedWait(ReadLock.this, nanos);
- }
- catch (InterruptedException ex) {
- lock.sync.cancelledWaitingReader();
- ie = ex;
- break;
- }
- if (lock.sync.startReadFromWaitingReader())
- return true;
- else {
- nanos = deadline - Utils.nanoTime();
- if (nanos <= 0) {
- lock.sync.cancelledWaitingReader();
- break;
- }
- }
- }
- }
- }
- // safeguard on interrupt or timeout:
- lock.writerLock_.signalWaiters();
- if (ie != null)
- throw ie;
- else
- return false; // timed out
- }
-
- /**
- * Attempts to release this lock.
- *
- * <p> If the number of readers is now zero then the lock
- * is made available for write lock attempts.
- */
- public void unlock() {
- switch (lock.sync.endRead()) {
- case Sync.NONE: return;
- case Sync.READER: lock.readerLock_.signalWaiters(); return;
- case Sync.WRITER: lock.writerLock_.signalWaiters(); return;
- }
- }
-
- /**
- * Throws {@code UnsupportedOperationException} because
- * {@code ReadLocks} do not support conditions.
- *
- * @throws UnsupportedOperationException always
- */
- public Condition newCondition() {
- throw new UnsupportedOperationException();
- }
-
- synchronized void signalWaiters() {
- notifyAll();
- }
-
- /**
- * Returns a string identifying this lock, as well as its lock state.
- * The state, in brackets, includes the String {@code "Read locks ="}
- * followed by the number of held read locks.
- *
- * @return a string identifying this lock, as well as its lock state
- */
- public String toString() {
- int r = lock.getReadLockCount();
- return super.toString() +
- "[Read locks = " + r + "]";
- }
-
- }
-
- /**
- * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
- */
- public static class WriteLock implements Lock, CondVar.ExclusiveLock,
- java.io.Serializable {
-
- private static final long serialVersionUID = -4992448646407690164L;
- final ReentrantReadWriteLock lock;
-
- /**
- * Constructor for use by subclasses
- *
- * @param lock the outer lock object
- * @throws NullPointerException if the lock is null
- */
- protected WriteLock(ReentrantReadWriteLock lock) {
- if (lock == null) throw new NullPointerException();
- this.lock = lock;
- }
-
- /**
- * Acquires the write lock.
- *
- * <p>Acquires the write lock if neither the read nor write lock
- * are held by another thread
- * and returns immediately, setting the write lock hold count to
- * one.
- *
- * <p>If the current thread already holds the write lock then the
- * hold count is incremented by one and the method returns
- * immediately.
- *
- * <p>If the lock is held by another thread then the current
- * thread becomes disabled for thread scheduling purposes and
- * lies dormant until the write lock has been acquired, at which
- * time the write lock hold count is set to one.
- */
- public void lock() {
- synchronized (this) {
- if (lock.sync.startWriteFromNewWriter()) return;
- boolean wasInterrupted = Thread.interrupted();
- try {
- while (true) {
- try {
- WriteLock.this.wait();
- }
- catch (InterruptedException ex) {
- wasInterrupted = true;
- // no need to notify; if we were notified,
- // we will act as notified, and succeed in
- // startWrite and return
- }
- if (lock.sync.startWriteFromWaitingWriter()) return;
- }
- }
- finally {
- if (wasInterrupted) Thread.currentThread().interrupt();
- }
- }
- }
-
- /**
- * Acquires the write lock unless the current thread is
- * {@linkplain Thread#interrupt interrupted}.
- *
- * <p>Acquires the write lock if neither the read nor write lock
- * are held by another thread
- * and returns immediately, setting the write lock hold count to
- * one.
- *
- * <p>If the current thread already holds this lock then the
- * hold count is incremented by one and the method returns
- * immediately.
- *
- * <p>If the lock is held by another thread then the current
- * thread becomes disabled for thread scheduling purposes and
- * lies dormant until one of two things happens:
- *
- * <ul>
- *
- * <li>The write lock is acquired by the current thread; or
- *
- * <li>Some other thread {@linkplain Thread#interrupt interrupts}
- * the current thread.
- *
- * </ul>
- *
- * <p>If the write lock is acquired by the current thread then the
- * lock hold count is set to one.
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method;
- * or
- *
- * <li>is {@linkplain Thread#interrupt interrupted} while
- * acquiring the write lock,
- *
- * </ul>
- *
- * then {@link InterruptedException} is thrown and the current
- * thread's interrupted status is cleared.
- *
- * <p>In this implementation, as this method is an explicit
- * interruption point, preference is given to responding to
- * the interrupt over normal or reentrant acquisition of the
- * lock.
- *
- * @throws InterruptedException if the current thread is interrupted
- */
- public void lockInterruptibly() throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- InterruptedException ie = null;
- synchronized (this) {
- if (!lock.sync.startWriteFromNewWriter()) {
- for (; ; ) {
- try {
- WriteLock.this.wait();
- if (lock.sync.startWriteFromWaitingWriter())
- return;
- }
- catch (InterruptedException ex) {
- lock.sync.cancelledWaitingWriter();
- WriteLock.this.notify();
- ie = ex;
- break;
- }
- }
- }
- }
- if (ie != null) {
- // Fall through outside synch on interrupt.
- // On exception, we may need to signal readers.
- // It is not worth checking here whether it is strictly necessary.
- lock.readerLock_.signalWaiters();
- throw ie;
- }
- }
-
- /**
- * Acquires the write lock only if it is not held by another thread
- * at the time of invocation.
- *
- * <p>Acquires the write lock if neither the read nor write lock
- * are held by another thread
- * and returns immediately with the value {@code true},
- * setting the write lock hold count to one. Even when this lock has
- * been set to use a fair ordering policy, a call to
- * {@code tryLock()} <em>will</em> immediately acquire the
- * lock if it is available, whether or not other threads are
- * currently waiting for the write lock. This &quot;barging&quot;
- * behavior can be useful in certain circumstances, even
- * though it breaks fairness. If you want to honor the
- * fairness setting for this lock, then use {@link
- * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
- * which is almost equivalent (it also detects interruption).
- *
- * <p> If the current thread already holds this lock then the
- * hold count is incremented by one and the method returns
- * {@code true}.
- *
- * <p>If the lock is held by another thread then this method
- * will return immediately with the value {@code false}.
- *
- * @return {@code true} if the lock was free and was acquired
- * by the current thread, or the write lock was already held
- * by the current thread; and {@code false} otherwise.
- */
- public boolean tryLock() {
- return lock.sync.startWrite();
- }
-
- /**
- * Acquires the write lock if it is not held by another thread
- * within the given waiting time and the current thread has
- * not been {@linkplain Thread#interrupt interrupted}.
- *
- * <p>Acquires the write lock if neither the read nor write lock
- * are held by another thread
- * and returns immediately with the value {@code true},
- * setting the write lock hold count to one. If this lock has been
- * set to use a fair ordering policy then an available lock
- * <em>will not</em> be acquired if any other threads are
- * waiting for the write lock. This is in contrast to the {@link
- * #tryLock()} method. If you want a timed {@code tryLock}
- * that does permit barging on a fair lock then combine the
- * timed and un-timed forms together:
- *
- * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
- * </pre>
- *
- * <p>If the current thread already holds this lock then the
- * hold count is incremented by one and the method returns
- * {@code true}.
- *
- * <p>If the lock is held by another thread then the current
- * thread becomes disabled for thread scheduling purposes and
- * lies dormant until one of three things happens:
- *
- * <ul>
- *
- * <li>The write lock is acquired by the current thread; or
- *
- * <li>Some other thread {@linkplain Thread#interrupt interrupts}
- * the current thread; or
- *
- * <li>The specified waiting time elapses
- *
- * </ul>
- *
- * <p>If the write lock is acquired then the value {@code true} is
- * returned and the write lock hold count is set to one.
- *
- * <p>If the current thread:
- *
- * <ul>
- *
- * <li>has its interrupted status set on entry to this method;
- * or
- *
- * <li>is {@linkplain Thread#interrupt interrupted} while
- * acquiring the write lock,
- *
- * </ul>
- *
- * then {@link InterruptedException} is thrown and the current
- * thread's interrupted status is cleared.
- *
- * <p>If the specified waiting time elapses then the value
- * {@code false} is returned. If the time is less than or
- * equal to zero, the method will not wait at all.
- *
- * <p>In this implementation, as this method is an explicit
- * interruption point, preference is given to responding to
- * the interrupt over normal or reentrant acquisition of the
- * lock, and over reporting the elapse of the waiting time.
- *
- * @param timeout the time to wait for the write lock
- * @param unit the time unit of the timeout argument
- *
- * @return {@code true} if the lock was free and was acquired
- * by the current thread, or the write lock was already held by the
- * current thread; and {@code false} if the waiting time
- * elapsed before the lock could be acquired.
- *
- * @throws InterruptedException if the current thread is interrupted
- * @throws NullPointerException if the time unit is null
- *
- */
- public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
- if (Thread.interrupted()) throw new InterruptedException();
- InterruptedException ie = null;
- long nanos = unit.toNanos(timeout);
- synchronized (this) {
- if (nanos <= 0)
- return lock.sync.startWrite();
- else if (lock.sync.startWriteFromNewWriter())
- return true;
- else {
- long deadline = Utils.nanoTime() + nanos;
- for (; ; ) {
- try {
- TimeUnit.NANOSECONDS.timedWait(WriteLock.this, nanos);
- }
- catch (InterruptedException ex) {
- lock.sync.cancelledWaitingWriter();
- WriteLock.this.notify();
- ie = ex;
- break;
- }
- if (lock.sync.startWriteFromWaitingWriter())
- return true;
- else {
- nanos = deadline - Utils.nanoTime();
- if (nanos <= 0) {
- lock.sync.cancelledWaitingWriter();
- WriteLock.this.notify();
- break;
- }
- }
- }
- }
- }
-
- lock.readerLock_.signalWaiters();
- if (ie != null)
- throw ie;
- else
- return false; // timed out
- }
-
- /**
- * Attempts to release this lock.
- *
- * <p>If the current thread is the holder of this lock then
- * the hold count is decremented. If the hold count is now
- * zero then the lock is released. If the current thread is
- * not the holder of this lock then {@link
- * IllegalMonitorStateException} is thrown.
- *
- * @throws IllegalMonitorStateException if the current thread does not
- * hold this lock.
- */
- public void unlock() {
- switch (lock.sync.endWrite()) {
- case Sync.NONE: return;
- case Sync.READER: lock.readerLock_.signalWaiters(); return;
- case Sync.WRITER: lock.writerLock_.signalWaiters(); return;
- }
- }
-
- /**
- * Returns a {@link Condition} instance for use with this
- * {@link Lock} instance.
- * <p>The returned {@link Condition} instance supports the same
- * usages as do the {@link Object} monitor methods ({@link
- * Object#wait() wait}, {@link Object#notify notify}, and {@link
- * Object#notifyAll notifyAll}) when used with the built-in
- * monitor lock.
- *
- * <ul>
- *
- * <li>If this write lock is not held when any {@link
- * Condition} method is called then an {@link
- * IllegalMonitorStateException} is thrown. (Read locks are
- * held independently of write locks, so are not checked or
- * affected. However it is essentially always an error to
- * invoke a condition waiting method when the current thread
- * has also acquired read locks, since other threads that
- * could unblock it will not be able to acquire the write
- * lock.)
- *
- * <li>When the condition {@linkplain Condition#await() waiting}
- * methods are called the write lock is released and, before
- * they return, the write lock is reacquired and the lock hold
- * count restored to what it was when the method was called.
- *
- * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
- * waiting then the wait will terminate, an {@link
- * InterruptedException} will be thrown, and the thread's
- * interrupted status will be cleared.
- *
- * <li> Waiting threads are signalled in FIFO order.
- *
- * <li>The ordering of lock reacquisition for threads returning
- * from waiting methods is the same as for threads initially
- * acquiring the lock, which is in the default case not specified,
- * but for <em>fair</em> locks favors those threads that have been
- * waiting the longest.
- *
- * </ul>
- *
- * @return the Condition object
- */
- public Condition newCondition() {
- return new CondVar(this);
- }
-
- synchronized void signalWaiters() {
- notify();
- }
-
- /**
- * Returns a string identifying this lock, as well as its lock
- * state. The state, in brackets includes either the String
- * {@code "Unlocked"} or the String {@code "Locked by"}
- * followed by the {@linkplain Thread#getName name} of the owning thread.
- *
- * @return a string identifying this lock, as well as its lock state
- */
- public String toString() {
- Thread o = lock.getOwner();
- return super.toString() + ((o == null) ?
- "[Unlocked]" :
- "[Locked by thread " + o.getName() + "]");
- }
-
- /**
- * Queries if this write lock is held by the current thread.
- * Identical in effect to {@link
- * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
- *
- * @return {@code true} if the current thread holds this lock and
- * {@code false} otherwise
- * @since 1.6
- */
- public boolean isHeldByCurrentThread() {
- return lock.sync.isWriteLockedByCurrentThread();
- }
-
- /**
- * Queries the number of holds on this write lock by the current
- * thread. A thread has a hold on a lock for each lock action
- * that is not matched by an unlock action. Identical in effect
- * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
- *
- * @return the number of holds on this lock by the current thread,
- * or zero if this lock is not held by the current thread
- * @since 1.6
- */
- public int getHoldCount() {
- return lock.sync.getWriteHoldCount();
- }
-
- }
-
- // Instrumentation and status
-
- /**
- * Returns {@code true} if this lock has fairness set true.
- *
- * @return {@code true} if this lock has fairness set true
- */
- public final boolean isFair() {
- return false;
- }
-
- /**
- * Returns the thread that currently owns the write lock, or
- * {@code null} if not owned. When this method is called by a
- * thread that is not the owner, the return value reflects a
- * best-effort approximation of current lock status. For example,
- * the owner may be momentarily {@code null} even if there are
- * threads trying to acquire the lock but have not yet done so.
- * This method is designed to facilitate construction of
- * subclasses that provide more extensive lock monitoring
- * facilities.
- *
- * @return the owner, or {@code null} if not owned
- */
- protected Thread getOwner() {
- return sync.getOwner();
- }
-
- /**
- * Queries the number of read locks held for this lock. This
- * method is designed for use in monitoring system state, not for
- * synchronization control.
- * @return the number of read locks held.
- */
- public int getReadLockCount() {
- return sync.getReadLockCount();
- }
-
- /**
- * Queries if the write lock is held by any thread. This method is
- * designed for use in monitoring system state, not for
- * synchronization control.
- *
- * @return {@code true} if any thread holds the write lock and
- * {@code false} otherwise
- */
- public boolean isWriteLocked() {
- return sync.isWriteLocked();
- }
-
- /**
- * Queries if the write lock is held by the current thread.
- *
- * @return {@code true} if the current thread holds the write lock and
- * {@code false} otherwise
- */
- public boolean isWriteLockedByCurrentThread() {
- return sync.isWriteLockedByCurrentThread();
- }
-
- /**
- * Queries the number of reentrant write holds on this lock by the
- * current thread. A writer thread has a hold on a lock for
- * each lock action that is not matched by an unlock action.
- *
- * @return the number of holds on the write lock by the current thread,
- * or zero if the write lock is not held by the current thread
- */
- public int getWriteHoldCount() {
- return sync.getWriteHoldCount();
- }
-
- /**
- * Queries the number of reentrant read holds on this lock by the
- * current thread. A reader thread has a hold on a lock for
- * each lock action that is not matched by an unlock action.
- *
- * @return the number of holds on the read lock by the current thread,
- * or zero if the read lock is not held by the current thread
- * @since 1.6
- */
- public int getReadHoldCount() {
- return sync.getReadHoldCount();
- }
-
-
-// /**
-// * Returns a collection containing threads that may be waiting to
-// * acquire the write lock. Because the actual set of threads may
-// * change dynamically while constructing this result, the returned
-// * collection is only a best-effort estimate. The elements of the
-// * returned collection are in no particular order. This method is
-// * designed to facilitate construction of subclasses that provide
-// * more extensive lock monitoring facilities.
-// * @return the collection of threads
-// */
-// protected Collection getQueuedWriterThreads() {
-// return sync.getExclusiveQueuedThreads();
-// }
-//
-// /**
-// * Returns a collection containing threads that may be waiting to
-// * acquire the read lock. Because the actual set of threads may
-// * change dynamically while constructing this result, the returned
-// * collection is only a best-effort estimate. The elements of the
-// * returned collection are in no particular order. This method is
-// * designed to facilitate construction of subclasses that provide
-// * more extensive lock monitoring facilities.
-// * @return the collection of threads
-// */
-// protected Collection getQueuedReaderThreads() {
-// return sync.getSharedQueuedThreads();
-// }
-//
- /**
- * Queries whether any threads are waiting to acquire the read or
- * write lock. Note that because cancellations may occur at any
- * time, a {@code true} return does not guarantee that any other
- * thread will ever acquire a lock. This method is designed
- * primarily for use in monitoring of the system state.
- *
- * @return {@code true} if there may be other threads waiting to
- * acquire the lock
- */
- public final boolean hasQueuedThreads() {
- return sync.hasQueuedThreads();
- }
-//
-// /**
-// * Queries whether the given thread is waiting to acquire either
-// * the read or write lock. Note that because cancellations may
-// * occur at any time, a <tt>true</tt> return does not guarantee
-// * that this thread will ever acquire a lock. This method is
-// * designed primarily for use in monitoring of the system state.
-// *
-// * @param thread the thread
-// * @return true if the given thread is queued waiting for this lock.
-// * @throws NullPointerException if thread is null
-// */
-// public final boolean hasQueuedThread(Thread thread) {
-// return sync.isQueued(thread);
-// }
-
- /**
- * Returns an estimate of the number of threads waiting to acquire
- * either the read or write lock. The value is only an estimate
- * because the number of threads may change dynamically while this
- * method traverses internal data structures. This method is
- * designed for use in monitoring of the system state, not for
- * synchronization control.
- *
- * @return the estimated number of threads waiting for this lock
- */
- public final int getQueueLength() {
- return sync.getQueueLength();
- }
-
-// /**
-// * Returns a collection containing threads that may be waiting to
-// * acquire either the read or write lock. Because the actual set
-// * of threads may change dynamically while constructing this
-// * result, the returned collection is only a best-effort estimate.
-// * The elements of the returned collection are in no particular
-// * order. This method is designed to facilitate construction of
-// * subclasses that provide more extensive monitoring facilities.
-// * @return the collection of threads
-// */
-// protected Collection getQueuedThreads() {
-// return sync.getQueuedThreads();
-// }
-//
-// /**
-// * Queries whether any threads are waiting on the given condition
-// * associated with the write lock. Note that because timeouts and
-// * interrupts may occur at any time, a <tt>true</tt> return does
-// * not guarantee that a future <tt>signal</tt> will awaken any
-// * threads. This method is designed primarily for use in
-// * monitoring of the system state.
-// * @param condition the condition
-// * @return <tt>true</tt> if there are any waiting threads.
-// * @throws IllegalMonitorStateException if this lock
-// * is not held
-// * @throws IllegalArgumentException if the given condition is
-// * not associated with this lock
-// * @throws NullPointerException if condition null
-// */
-// public boolean hasWaiters(Condition condition) {
-// if (condition == null)
-// throw new NullPointerException();
-// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
-// throw new IllegalArgumentException("not owner");
-// return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
-// }
-
-// /**
-// * Returns an estimate of the number of threads waiting on the
-// * given condition associated with the write lock. Note that because
-// * timeouts and interrupts may occur at any time, the estimate
-// * serves only as an upper bound on the actual number of waiters.
-// * This method is designed for use in monitoring of the system
-// * state, not for synchronization control.
-// * @param condition the condition
-// * @return the estimated number of waiting threads.
-// * @throws IllegalMonitorStateException if this lock
-// * is not held
-// * @throws IllegalArgumentException if the given condition is
-// * not associated with this lock
-// * @throws NullPointerException if condition null
-// */
-// public int getWaitQueueLength(Condition condition) {
-// if (condition == null)
-// throw new NullPointerException();
-// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
-// throw new IllegalArgumentException("not owner");
-// return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
-// }
-//
-// /**
-// * Returns a collection containing those threads that may be
-// * waiting on the given condition associated with the write lock.
-// * Because the actual set of threads may change dynamically while
-// * constructing this result, the returned collection is only a
-// * best-effort estimate. The elements of the returned collection
-// * are in no particular order. This method is designed to
-// * facilitate construction of subclasses that provide more
-// * extensive condition monitoring facilities.
-// * @param condition the condition
-// * @return the collection of threads
-// * @throws IllegalMonitorStateException if this lock
-// * is not held
-// * @throws IllegalArgumentException if the given condition is
-// * not associated with this lock
-// * @throws NullPointerException if condition null
-// */
-// protected Collection getWaitingThreads(Condition condition) {
-// if (condition == null)
-// throw new NullPointerException();
-// if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
-// throw new IllegalArgumentException("not owner");
-// return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
-// }
-
- /**
- * Returns a string identifying this lock, as well as its lock state.
- * The state, in brackets, includes the String {@code "Write locks ="}
- * followed by the number of reentrantly held write locks, and the
- * String {@code "Read locks ="} followed by the number of held
- * read locks.
- *
- * @return a string identifying this lock, as well as its lock state
- */
- public String toString() {
- return super.toString() +
- "[Write locks = " + getWriteHoldCount() +
- ", Read locks = " + getReadLockCount() + "]";
- }
-}