mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			1935 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			1935 lines
		
	
	
		
			73 KiB
		
	
	
	
		
			Java
		
	
	
	
| /*
 | |
|  * 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 java.util.concurrent.locks;
 | |
| import java.util.*;
 | |
| import java.util.concurrent.*;
 | |
| import java.util.concurrent.atomic.*;
 | |
| import sun.misc.Unsafe;
 | |
| 
 | |
| /**
 | |
|  * A version of {@link AbstractQueuedSynchronizer} in
 | |
|  * which synchronization state is maintained as a <tt>long</tt>.
 | |
|  * This class has exactly the same structure, properties, and methods
 | |
|  * as <tt>AbstractQueuedSynchronizer</tt> with the exception
 | |
|  * that all state-related parameters and results are defined
 | |
|  * as <tt>long</tt> rather than <tt>int</tt>. This class
 | |
|  * may be useful when creating synchronizers such as
 | |
|  * multilevel locks and barriers that require
 | |
|  * 64 bits of state.
 | |
|  *
 | |
|  * <p>See {@link AbstractQueuedSynchronizer} for usage
 | |
|  * notes and examples.
 | |
|  *
 | |
|  * @since 1.6
 | |
|  * @author Doug Lea
 | |
|  */
 | |
| public abstract class AbstractQueuedLongSynchronizer
 | |
|     extends AbstractOwnableSynchronizer
 | |
|     implements java.io.Serializable {
 | |
| 
 | |
|     private static final long serialVersionUID = 7373984972572414692L;
 | |
| 
 | |
|     /*
 | |
|       To keep sources in sync, the remainder of this source file is
 | |
|       exactly cloned from AbstractQueuedSynchronizer, replacing class
 | |
|       name and changing ints related with sync state to longs. Please
 | |
|       keep it that way.
 | |
|     */
 | |
| 
 | |
|     /**
 | |
|      * Creates a new <tt>AbstractQueuedLongSynchronizer</tt> instance
 | |
|      * with initial synchronization state of zero.
 | |
|      */
 | |
|     protected AbstractQueuedLongSynchronizer() { }
 | |
| 
 | |
|     /**
 | |
|      * Wait queue node class.
 | |
|      *
 | |
|      * <p>The wait queue is a variant of a "CLH" (Craig, Landin, and
 | |
|      * Hagersten) lock queue. CLH locks are normally used for
 | |
|      * spinlocks.  We instead use them for blocking synchronizers, but
 | |
|      * use the same basic tactic of holding some of the control
 | |
|      * information about a thread in the predecessor of its node.  A
 | |
|      * "status" field in each node keeps track of whether a thread
 | |
|      * should block.  A node is signalled when its predecessor
 | |
|      * releases.  Each node of the queue otherwise serves as a
 | |
|      * specific-notification-style monitor holding a single waiting
 | |
|      * thread. The status field does NOT control whether threads are
 | |
|      * granted locks etc though.  A thread may try to acquire if it is
 | |
|      * first in the queue. But being first does not guarantee success;
 | |
|      * it only gives the right to contend.  So the currently released
 | |
|      * contender thread may need to rewait.
 | |
|      *
 | |
|      * <p>To enqueue into a CLH lock, you atomically splice it in as new
 | |
|      * tail. To dequeue, you just set the head field.
 | |
|      * <pre>
 | |
|      *      +------+  prev +-----+       +-----+
 | |
|      * head |      | <---- |     | <---- |     |  tail
 | |
|      *      +------+       +-----+       +-----+
 | |
|      * </pre>
 | |
|      *
 | |
|      * <p>Insertion into a CLH queue requires only a single atomic
 | |
|      * operation on "tail", so there is a simple atomic point of
 | |
|      * demarcation from unqueued to queued. Similarly, dequeing
 | |
|      * involves only updating the "head". However, it takes a bit
 | |
|      * more work for nodes to determine who their successors are,
 | |
|      * in part to deal with possible cancellation due to timeouts
 | |
|      * and interrupts.
 | |
|      *
 | |
|      * <p>The "prev" links (not used in original CLH locks), are mainly
 | |
|      * needed to handle cancellation. If a node is cancelled, its
 | |
|      * successor is (normally) relinked to a non-cancelled
 | |
|      * predecessor. For explanation of similar mechanics in the case
 | |
|      * of spin locks, see the papers by Scott and Scherer at
 | |
|      * http://www.cs.rochester.edu/u/scott/synchronization/
 | |
|      *
 | |
|      * <p>We also use "next" links to implement blocking mechanics.
 | |
|      * The thread id for each node is kept in its own node, so a
 | |
|      * predecessor signals the next node to wake up by traversing
 | |
|      * next link to determine which thread it is.  Determination of
 | |
|      * successor must avoid races with newly queued nodes to set
 | |
|      * the "next" fields of their predecessors.  This is solved
 | |
|      * when necessary by checking backwards from the atomically
 | |
|      * updated "tail" when a node's successor appears to be null.
 | |
|      * (Or, said differently, the next-links are an optimization
 | |
|      * so that we don't usually need a backward scan.)
 | |
|      *
 | |
|      * <p>Cancellation introduces some conservatism to the basic
 | |
|      * algorithms.  Since we must poll for cancellation of other
 | |
|      * nodes, we can miss noticing whether a cancelled node is
 | |
|      * ahead or behind us. This is dealt with by always unparking
 | |
|      * successors upon cancellation, allowing them to stabilize on
 | |
|      * a new predecessor.
 | |
|      *
 | |
|      * <p>CLH queues need a dummy header node to get started. But
 | |
|      * we don't create them on construction, because it would be wasted
 | |
|      * effort if there is never contention. Instead, the node
 | |
|      * is constructed and head and tail pointers are set upon first
 | |
|      * contention.
 | |
|      *
 | |
|      * <p>Threads waiting on Conditions use the same nodes, but
 | |
|      * use an additional link. Conditions only need to link nodes
 | |
|      * in simple (non-concurrent) linked queues because they are
 | |
|      * only accessed when exclusively held.  Upon await, a node is
 | |
|      * inserted into a condition queue.  Upon signal, the node is
 | |
|      * transferred to the main queue.  A special value of status
 | |
|      * field is used to mark which queue a node is on.
 | |
|      *
 | |
|      * <p>Thanks go to Dave Dice, Mark Moir, Victor Luchangco, Bill
 | |
|      * Scherer and Michael Scott, along with members of JSR-166
 | |
|      * expert group, for helpful ideas, discussions, and critiques
 | |
|      * on the design of this class.
 | |
|      */
 | |
|     static final class Node {
 | |
|         /** waitStatus value to indicate thread has cancelled */
 | |
|         static final int CANCELLED =  1;
 | |
|         /** waitStatus value to indicate successor's thread needs unparking */
 | |
|         static final int SIGNAL    = -1;
 | |
|         /** waitStatus value to indicate thread is waiting on condition */
 | |
|         static final int CONDITION = -2;
 | |
|         /** Marker to indicate a node is waiting in shared mode */
 | |
|         static final Node SHARED = new Node();
 | |
|         /** Marker to indicate a node is waiting in exclusive mode */
 | |
|         static final Node EXCLUSIVE = null;
 | |
| 
 | |
|         /**
 | |
|          * Status field, taking on only the values:
 | |
|          *   SIGNAL:     The successor of this node is (or will soon be)
 | |
|          *               blocked (via park), so the current node must
 | |
|          *               unpark its successor when it releases or
 | |
|          *               cancels. To avoid races, acquire methods must
 | |
|          *               first indicate they need a signal,
 | |
|          *               then retry the atomic acquire, and then,
 | |
|          *               on failure, block.
 | |
|          *   CANCELLED:  This node is cancelled due to timeout or interrupt.
 | |
|          *               Nodes never leave this state. In particular,
 | |
|          *               a thread with cancelled node never again blocks.
 | |
|          *   CONDITION:  This node is currently on a condition queue.
 | |
|          *               It will not be used as a sync queue node until
 | |
|          *               transferred. (Use of this value here
 | |
|          *               has nothing to do with the other uses
 | |
|          *               of the field, but simplifies mechanics.)
 | |
|          *   0:          None of the above
 | |
|          *
 | |
|          * The values are arranged numerically to simplify use.
 | |
|          * Non-negative values mean that a node doesn't need to
 | |
|          * signal. So, most code doesn't need to check for particular
 | |
|          * values, just for sign.
 | |
|          *
 | |
|          * The field is initialized to 0 for normal sync nodes, and
 | |
|          * CONDITION for condition nodes.  It is modified only using
 | |
|          * CAS.
 | |
|          */
 | |
|         volatile int waitStatus;
 | |
| 
 | |
|         /**
 | |
|          * Link to predecessor node that current node/thread relies on
 | |
|          * for checking waitStatus. Assigned during enqueing, and nulled
 | |
|          * out (for sake of GC) only upon dequeuing.  Also, upon
 | |
|          * cancellation of a predecessor, we short-circuit while
 | |
|          * finding a non-cancelled one, which will always exist
 | |
|          * because the head node is never cancelled: A node becomes
 | |
|          * head only as a result of successful acquire. A
 | |
|          * cancelled thread never succeeds in acquiring, and a thread only
 | |
|          * cancels itself, not any other node.
 | |
|          */
 | |
|         volatile Node prev;
 | |
| 
 | |
|         /**
 | |
|          * Link to the successor node that the current node/thread
 | |
|          * unparks upon release. Assigned once during enqueuing, and
 | |
|          * nulled out (for sake of GC) when no longer needed.  Upon
 | |
|          * cancellation, we cannot adjust this field, but can notice
 | |
|          * status and bypass the node if cancelled.  The enq operation
 | |
|          * does not assign next field of a predecessor until after
 | |
|          * attachment, so seeing a null next field does not
 | |
|          * necessarily mean that node is at end of queue. However, if
 | |
|          * a next field appears to be null, we can scan prev's from
 | |
|          * the tail to double-check.
 | |
|          */
 | |
|         volatile Node next;
 | |
| 
 | |
|         /**
 | |
|          * The thread that enqueued this node.  Initialized on
 | |
|          * construction and nulled out after use.
 | |
|          */
 | |
|         volatile Thread thread;
 | |
| 
 | |
|         /**
 | |
|          * Link to next node waiting on condition, or the special
 | |
|          * value SHARED.  Because condition queues are accessed only
 | |
|          * when holding in exclusive mode, we just need a simple
 | |
|          * linked queue to hold nodes while they are waiting on
 | |
|          * conditions. They are then transferred to the queue to
 | |
|          * re-acquire. And because conditions can only be exclusive,
 | |
|          * we save a field by using special value to indicate shared
 | |
|          * mode.
 | |
|          */
 | |
|         Node nextWaiter;
 | |
| 
 | |
|         /**
 | |
|          * Returns true if node is waiting in shared mode
 | |
|          */
 | |
|         final boolean isShared() {
 | |
|             return nextWaiter == SHARED;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns previous node, or throws NullPointerException if
 | |
|          * null.  Use when predecessor cannot be null.
 | |
|          * @return the predecessor of this node
 | |
|          */
 | |
|         final Node predecessor() throws NullPointerException {
 | |
|             Node p = prev;
 | |
|             if (p == null)
 | |
|                 throw new NullPointerException();
 | |
|             else
 | |
|                 return p;
 | |
|         }
 | |
| 
 | |
|         Node() {    // Used to establish initial head or SHARED marker
 | |
|         }
 | |
| 
 | |
|         Node(Thread thread, Node mode) {     // Used by addWaiter
 | |
|             this.nextWaiter = mode;
 | |
|             this.thread = thread;
 | |
|         }
 | |
| 
 | |
|         Node(Thread thread, int waitStatus) { // Used by Condition
 | |
|             this.waitStatus = waitStatus;
 | |
|             this.thread = thread;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Head of the wait queue, lazily initialized.  Except for
 | |
|      * initialization, it is modified only via method setHead.  Note:
 | |
|      * If head exists, its waitStatus is guaranteed not to be
 | |
|      * CANCELLED.
 | |
|      */
 | |
|     private transient volatile Node head;
 | |
| 
 | |
|     /**
 | |
|      * Tail of the wait queue, lazily initialized.  Modified only via
 | |
|      * method enq to add new wait node.
 | |
|      */
 | |
|     private transient volatile Node tail;
 | |
| 
 | |
|     /**
 | |
|      * The synchronization state.
 | |
|      */
 | |
|     private volatile long state;
 | |
| 
 | |
|     /**
 | |
|      * Returns the current value of synchronization state.
 | |
|      * This operation has memory semantics of a <tt>volatile</tt> read.
 | |
|      * @return current state value
 | |
|      */
 | |
|     protected final long getState() {
 | |
|         return state;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the value of synchronization state.
 | |
|      * This operation has memory semantics of a <tt>volatile</tt> write.
 | |
|      * @param newState the new state value
 | |
|      */
 | |
|     protected final void setState(long newState) {
 | |
|         state = newState;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Atomically sets synchronization state to the given updated
 | |
|      * value if the current state value equals the expected value.
 | |
|      * This operation has memory semantics of a <tt>volatile</tt> read
 | |
|      * and write.
 | |
|      *
 | |
|      * @param expect the expected value
 | |
|      * @param update the new value
 | |
|      * @return true if successful. False return indicates that the actual
 | |
|      *         value was not equal to the expected value.
 | |
|      */
 | |
|     protected final boolean compareAndSetState(long expect, long update) {
 | |
|         // See below for intrinsics setup to support this
 | |
|         return unsafe.compareAndSwapLong(this, stateOffset, expect, update);
 | |
|     }
 | |
| 
 | |
|     // Queuing utilities
 | |
| 
 | |
|     /**
 | |
|      * The number of nanoseconds for which it is faster to spin
 | |
|      * rather than to use timed park. A rough estimate suffices
 | |
|      * to improve responsiveness with very short timeouts.
 | |
|      */
 | |
|     static final long spinForTimeoutThreshold = 1000L;
 | |
| 
 | |
|     /**
 | |
|      * Inserts node into queue, initializing if necessary. See picture above.
 | |
|      * @param node the node to insert
 | |
|      * @return node's predecessor
 | |
|      */
 | |
|     private Node enq(final Node node) {
 | |
|         for (;;) {
 | |
|             Node t = tail;
 | |
|             if (t == null) { // Must initialize
 | |
|                 Node h = new Node(); // Dummy header
 | |
|                 h.next = node;
 | |
|                 node.prev = h;
 | |
|                 if (compareAndSetHead(h)) {
 | |
|                     tail = node;
 | |
|                     return h;
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 node.prev = t;
 | |
|                 if (compareAndSetTail(t, node)) {
 | |
|                     t.next = node;
 | |
|                     return t;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Creates and enqueues node for given thread and mode.
 | |
|      *
 | |
|      * @param current the thread
 | |
|      * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
 | |
|      * @return the new node
 | |
|      */
 | |
|     private Node addWaiter(Node mode) {
 | |
|         Node node = new Node(Thread.currentThread(), mode);
 | |
|         // Try the fast path of enq; backup to full enq on failure
 | |
|         Node pred = tail;
 | |
|         if (pred != null) {
 | |
|             node.prev = pred;
 | |
|             if (compareAndSetTail(pred, node)) {
 | |
|                 pred.next = node;
 | |
|                 return node;
 | |
|             }
 | |
|         }
 | |
|         enq(node);
 | |
|         return node;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets head of queue to be node, thus dequeuing. Called only by
 | |
|      * acquire methods.  Also nulls out unused fields for sake of GC
 | |
|      * and to suppress unnecessary signals and traversals.
 | |
|      *
 | |
|      * @param node the node
 | |
|      */
 | |
|     private void setHead(Node node) {
 | |
|         head = node;
 | |
|         node.thread = null;
 | |
|         node.prev = null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Wakes up node's successor, if one exists.
 | |
|      *
 | |
|      * @param node the node
 | |
|      */
 | |
|     private void unparkSuccessor(Node node) {
 | |
|         /*
 | |
|          * Try to clear status in anticipation of signalling.  It is
 | |
|          * OK if this fails or if status is changed by waiting thread.
 | |
|          */
 | |
|         compareAndSetWaitStatus(node, Node.SIGNAL, 0);
 | |
| 
 | |
|         /*
 | |
|          * Thread to unpark is held in successor, which is normally
 | |
|          * just the next node.  But if cancelled or apparently null,
 | |
|          * traverse backwards from tail to find the actual
 | |
|          * non-cancelled successor.
 | |
|          */
 | |
|         Node s = node.next;
 | |
|         if (s == null || s.waitStatus > 0) {
 | |
|             s = null;
 | |
|             for (Node t = tail; t != null && t != node; t = t.prev)
 | |
|                 if (t.waitStatus <= 0)
 | |
|                     s = t;
 | |
|         }
 | |
|         if (s != null)
 | |
|             LockSupport.unpark(s.thread);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets head of queue, and checks if successor may be waiting
 | |
|      * in shared mode, if so propagating if propagate > 0.
 | |
|      *
 | |
|      * @param pred the node holding waitStatus for node
 | |
|      * @param node the node
 | |
|      * @param propagate the return value from a tryAcquireShared
 | |
|      */
 | |
|     private void setHeadAndPropagate(Node node, long propagate) {
 | |
|         setHead(node);
 | |
|         if (propagate > 0 && node.waitStatus != 0) {
 | |
|             /*
 | |
|              * Don't bother fully figuring out successor.  If it
 | |
|              * looks null, call unparkSuccessor anyway to be safe.
 | |
|              */
 | |
|             Node s = node.next;
 | |
|             if (s == null || s.isShared())
 | |
|                 unparkSuccessor(node);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     // Utilities for various versions of acquire
 | |
| 
 | |
|     /**
 | |
|      * Cancels an ongoing attempt to acquire.
 | |
|      *
 | |
|      * @param node the node
 | |
|      */
 | |
|     private void cancelAcquire(Node node) {
 | |
|         if (node != null) { // Ignore if node doesn't exist
 | |
|             node.thread = null;
 | |
|             // Can use unconditional write instead of CAS here
 | |
|             node.waitStatus = Node.CANCELLED;
 | |
|             unparkSuccessor(node);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks and updates status for a node that failed to acquire.
 | |
|      * Returns true if thread should block. This is the main signal
 | |
|      * control in all acquire loops.  Requires that pred == node.prev
 | |
|      *
 | |
|      * @param pred node's predecessor holding status
 | |
|      * @param node the node
 | |
|      * @return {@code true} if thread should block
 | |
|      */
 | |
|     private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
 | |
|         int s = pred.waitStatus;
 | |
|         if (s < 0)
 | |
|             /*
 | |
|              * This node has already set status asking a release
 | |
|              * to signal it, so it can safely park
 | |
|              */
 | |
|             return true;
 | |
|         if (s > 0)
 | |
|             /*
 | |
|              * Predecessor was cancelled. Move up to its predecessor
 | |
|              * and indicate retry.
 | |
|              */
 | |
|             node.prev = pred.prev;
 | |
|         else
 | |
|             /*
 | |
|              * Indicate that we need a signal, but don't park yet. Caller
 | |
|              * will need to retry to make sure it cannot acquire before
 | |
|              * parking.
 | |
|              */
 | |
|             compareAndSetWaitStatus(pred, 0, Node.SIGNAL);
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Convenience method to interrupt current thread.
 | |
|      */
 | |
|     private static void selfInterrupt() {
 | |
|         Thread.currentThread().interrupt();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Convenience method to park and then check if interrupted
 | |
|      *
 | |
|      * @return {@code true} if interrupted
 | |
|      */
 | |
|     private final boolean parkAndCheckInterrupt() {
 | |
|         LockSupport.park(this);
 | |
|         return Thread.interrupted();
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Various flavors of acquire, varying in exclusive/shared and
 | |
|      * control modes.  Each is mostly the same, but annoyingly
 | |
|      * different.  Only a little bit of factoring is possible due to
 | |
|      * interactions of exception mechanics (including ensuring that we
 | |
|      * cancel if tryAcquire throws exception) and other control, at
 | |
|      * least not without hurting performance too much.
 | |
|      */
 | |
| 
 | |
|     /**
 | |
|      * Acquires in exclusive uninterruptible mode for thread already in
 | |
|      * queue. Used by condition wait methods as well as acquire.
 | |
|      *
 | |
|      * @param node the node
 | |
|      * @param arg the acquire argument
 | |
|      * @return {@code true} if interrupted while waiting
 | |
|      */
 | |
|     final boolean acquireQueued(final Node node, long arg) {
 | |
|         try {
 | |
|             boolean interrupted = false;
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head && tryAcquire(arg)) {
 | |
|                     setHead(node);
 | |
|                     p.next = null; // help GC
 | |
|                     return interrupted;
 | |
|                 }
 | |
|                 if (shouldParkAfterFailedAcquire(p, node) &&
 | |
|                     parkAndCheckInterrupt())
 | |
|                     interrupted = true;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in exclusive interruptible mode.
 | |
|      * @param arg the acquire argument
 | |
|      */
 | |
|     private void doAcquireInterruptibly(long arg)
 | |
|         throws InterruptedException {
 | |
|         final Node node = addWaiter(Node.EXCLUSIVE);
 | |
|         try {
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head && tryAcquire(arg)) {
 | |
|                     setHead(node);
 | |
|                     p.next = null; // help GC
 | |
|                     return;
 | |
|                 }
 | |
|                 if (shouldParkAfterFailedAcquire(p, node) &&
 | |
|                     parkAndCheckInterrupt())
 | |
|                     break;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|         // Arrive here only if interrupted
 | |
|         cancelAcquire(node);
 | |
|         throw new InterruptedException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in exclusive timed mode.
 | |
|      *
 | |
|      * @param arg the acquire argument
 | |
|      * @param nanosTimeout max wait time
 | |
|      * @return {@code true} if acquired
 | |
|      */
 | |
|     private boolean doAcquireNanos(long arg, long nanosTimeout)
 | |
|         throws InterruptedException {
 | |
|         long lastTime = System.nanoTime();
 | |
|         final Node node = addWaiter(Node.EXCLUSIVE);
 | |
|         try {
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head && tryAcquire(arg)) {
 | |
|                     setHead(node);
 | |
|                     p.next = null; // help GC
 | |
|                     return true;
 | |
|                 }
 | |
|                 if (nanosTimeout <= 0) {
 | |
|                     cancelAcquire(node);
 | |
|                     return false;
 | |
|                 }
 | |
|                 if (nanosTimeout > spinForTimeoutThreshold &&
 | |
|                     shouldParkAfterFailedAcquire(p, node))
 | |
|                     LockSupport.parkNanos(this, nanosTimeout);
 | |
|                 long now = System.nanoTime();
 | |
|                 nanosTimeout -= now - lastTime;
 | |
|                 lastTime = now;
 | |
|                 if (Thread.interrupted())
 | |
|                     break;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|         // Arrive here only if interrupted
 | |
|         cancelAcquire(node);
 | |
|         throw new InterruptedException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in shared uninterruptible mode.
 | |
|      * @param arg the acquire argument
 | |
|      */
 | |
|     private void doAcquireShared(long arg) {
 | |
|         final Node node = addWaiter(Node.SHARED);
 | |
|         try {
 | |
|             boolean interrupted = false;
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head) {
 | |
|                     long r = tryAcquireShared(arg);
 | |
|                     if (r >= 0) {
 | |
|                         setHeadAndPropagate(node, r);
 | |
|                         p.next = null; // help GC
 | |
|                         if (interrupted)
 | |
|                             selfInterrupt();
 | |
|                         return;
 | |
|                     }
 | |
|                 }
 | |
|                 if (shouldParkAfterFailedAcquire(p, node) &&
 | |
|                     parkAndCheckInterrupt())
 | |
|                     interrupted = true;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in shared interruptible mode.
 | |
|      * @param arg the acquire argument
 | |
|      */
 | |
|     private void doAcquireSharedInterruptibly(long arg)
 | |
|         throws InterruptedException {
 | |
|         final Node node = addWaiter(Node.SHARED);
 | |
|         try {
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head) {
 | |
|                     long r = tryAcquireShared(arg);
 | |
|                     if (r >= 0) {
 | |
|                         setHeadAndPropagate(node, r);
 | |
|                         p.next = null; // help GC
 | |
|                         return;
 | |
|                     }
 | |
|                 }
 | |
|                 if (shouldParkAfterFailedAcquire(p, node) &&
 | |
|                     parkAndCheckInterrupt())
 | |
|                     break;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|         // Arrive here only if interrupted
 | |
|         cancelAcquire(node);
 | |
|         throw new InterruptedException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in shared timed mode.
 | |
|      *
 | |
|      * @param arg the acquire argument
 | |
|      * @param nanosTimeout max wait time
 | |
|      * @return {@code true} if acquired
 | |
|      */
 | |
|     private boolean doAcquireSharedNanos(long arg, long nanosTimeout)
 | |
|         throws InterruptedException {
 | |
| 
 | |
|         long lastTime = System.nanoTime();
 | |
|         final Node node = addWaiter(Node.SHARED);
 | |
|         try {
 | |
|             for (;;) {
 | |
|                 final Node p = node.predecessor();
 | |
|                 if (p == head) {
 | |
|                     long r = tryAcquireShared(arg);
 | |
|                     if (r >= 0) {
 | |
|                         setHeadAndPropagate(node, r);
 | |
|                         p.next = null; // help GC
 | |
|                         return true;
 | |
|                     }
 | |
|                 }
 | |
|                 if (nanosTimeout <= 0) {
 | |
|                     cancelAcquire(node);
 | |
|                     return false;
 | |
|                 }
 | |
|                 if (nanosTimeout > spinForTimeoutThreshold &&
 | |
|                     shouldParkAfterFailedAcquire(p, node))
 | |
|                     LockSupport.parkNanos(this, nanosTimeout);
 | |
|                 long now = System.nanoTime();
 | |
|                 nanosTimeout -= now - lastTime;
 | |
|                 lastTime = now;
 | |
|                 if (Thread.interrupted())
 | |
|                     break;
 | |
|             }
 | |
|         } catch (RuntimeException ex) {
 | |
|             cancelAcquire(node);
 | |
|             throw ex;
 | |
|         }
 | |
|         // Arrive here only if interrupted
 | |
|         cancelAcquire(node);
 | |
|         throw new InterruptedException();
 | |
|     }
 | |
| 
 | |
|     // Main exported methods
 | |
| 
 | |
|     /**
 | |
|      * Attempts to acquire in exclusive mode. This method should query
 | |
|      * if the state of the object permits it to be acquired in the
 | |
|      * exclusive mode, and if so to acquire it.
 | |
|      *
 | |
|      * <p>This method is always invoked by the thread performing
 | |
|      * acquire.  If this method reports failure, the acquire method
 | |
|      * may queue the thread, if it is not already queued, until it is
 | |
|      * signalled by a release from some other thread. This can be used
 | |
|      * to implement method {@link Lock#tryLock()}.
 | |
|      *
 | |
|      * <p>The default
 | |
|      * implementation throws {@link UnsupportedOperationException}.
 | |
|      *
 | |
|      * @param arg the acquire argument. This value is always the one
 | |
|      *        passed to an acquire method, or is the value saved on entry
 | |
|      *        to a condition wait.  The value is otherwise uninterpreted
 | |
|      *        and can represent anything you like.
 | |
|      * @return {@code true} if successful. Upon success, this object has
 | |
|      *         been acquired.
 | |
|      * @throws IllegalMonitorStateException if acquiring would place this
 | |
|      *         synchronizer in an illegal state. This exception must be
 | |
|      *         thrown in a consistent fashion for synchronization to work
 | |
|      *         correctly.
 | |
|      * @throws UnsupportedOperationException if exclusive mode is not supported
 | |
|      */
 | |
|     protected boolean tryAcquire(long arg) {
 | |
|         throw new UnsupportedOperationException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempts to set the state to reflect a release in exclusive
 | |
|      * mode.
 | |
|      *
 | |
|      * <p>This method is always invoked by the thread performing release.
 | |
|      *
 | |
|      * <p>The default implementation throws
 | |
|      * {@link UnsupportedOperationException}.
 | |
|      *
 | |
|      * @param arg the release argument. This value is always the one
 | |
|      *        passed to a release method, or the current state value upon
 | |
|      *        entry to a condition wait.  The value is otherwise
 | |
|      *        uninterpreted and can represent anything you like.
 | |
|      * @return {@code true} if this object is now in a fully released
 | |
|      *         state, so that any waiting threads may attempt to acquire;
 | |
|      *         and {@code false} otherwise.
 | |
|      * @throws IllegalMonitorStateException if releasing would place this
 | |
|      *         synchronizer in an illegal state. This exception must be
 | |
|      *         thrown in a consistent fashion for synchronization to work
 | |
|      *         correctly.
 | |
|      * @throws UnsupportedOperationException if exclusive mode is not supported
 | |
|      */
 | |
|     protected boolean tryRelease(long arg) {
 | |
|         throw new UnsupportedOperationException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempts to acquire in shared mode. This method should query if
 | |
|      * the state of the object permits it to be acquired in the shared
 | |
|      * mode, and if so to acquire it.
 | |
|      *
 | |
|      * <p>This method is always invoked by the thread performing
 | |
|      * acquire.  If this method reports failure, the acquire method
 | |
|      * may queue the thread, if it is not already queued, until it is
 | |
|      * signalled by a release from some other thread.
 | |
|      *
 | |
|      * <p>The default implementation throws {@link
 | |
|      * UnsupportedOperationException}.
 | |
|      *
 | |
|      * @param arg the acquire argument. This value is always the one
 | |
|      *        passed to an acquire method, or is the value saved on entry
 | |
|      *        to a condition wait.  The value is otherwise uninterpreted
 | |
|      *        and can represent anything you like.
 | |
|      * @return a negative value on failure; zero if acquisition in shared
 | |
|      *         mode succeeded but no subsequent shared-mode acquire can
 | |
|      *         succeed; and a positive value if acquisition in shared
 | |
|      *         mode succeeded and subsequent shared-mode acquires might
 | |
|      *         also succeed, in which case a subsequent waiting thread
 | |
|      *         must check availability. (Support for three different
 | |
|      *         return values enables this method to be used in contexts
 | |
|      *         where acquires only sometimes act exclusively.)  Upon
 | |
|      *         success, this object has been acquired.
 | |
|      * @throws IllegalMonitorStateException if acquiring would place this
 | |
|      *         synchronizer in an illegal state. This exception must be
 | |
|      *         thrown in a consistent fashion for synchronization to work
 | |
|      *         correctly.
 | |
|      * @throws UnsupportedOperationException if shared mode is not supported
 | |
|      */
 | |
|     protected long tryAcquireShared(long arg) {
 | |
|         throw new UnsupportedOperationException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempts to set the state to reflect a release in shared mode.
 | |
|      *
 | |
|      * <p>This method is always invoked by the thread performing release.
 | |
|      *
 | |
|      * <p>The default implementation throws
 | |
|      * {@link UnsupportedOperationException}.
 | |
|      *
 | |
|      * @param arg the release argument. This value is always the one
 | |
|      *        passed to a release method, or the current state value upon
 | |
|      *        entry to a condition wait.  The value is otherwise
 | |
|      *        uninterpreted and can represent anything you like.
 | |
|      * @return {@code true} if this release of shared mode may permit a
 | |
|      *         waiting acquire (shared or exclusive) to succeed; and
 | |
|      *         {@code false} otherwise
 | |
|      * @throws IllegalMonitorStateException if releasing would place this
 | |
|      *         synchronizer in an illegal state. This exception must be
 | |
|      *         thrown in a consistent fashion for synchronization to work
 | |
|      *         correctly.
 | |
|      * @throws UnsupportedOperationException if shared mode is not supported
 | |
|      */
 | |
|     protected boolean tryReleaseShared(long arg) {
 | |
|         throw new UnsupportedOperationException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns {@code true} if synchronization is held exclusively with
 | |
|      * respect to the current (calling) thread.  This method is invoked
 | |
|      * upon each call to a non-waiting {@link ConditionObject} method.
 | |
|      * (Waiting methods instead invoke {@link #release}.)
 | |
|      *
 | |
|      * <p>The default implementation throws {@link
 | |
|      * UnsupportedOperationException}. This method is invoked
 | |
|      * internally only within {@link ConditionObject} methods, so need
 | |
|      * not be defined if conditions are not used.
 | |
|      *
 | |
|      * @return {@code true} if synchronization is held exclusively;
 | |
|      *         {@code false} otherwise
 | |
|      * @throws UnsupportedOperationException if conditions are not supported
 | |
|      */
 | |
|     protected boolean isHeldExclusively() {
 | |
|         throw new UnsupportedOperationException();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in exclusive mode, ignoring interrupts.  Implemented
 | |
|      * by invoking at least once {@link #tryAcquire},
 | |
|      * returning on success.  Otherwise the thread is queued, possibly
 | |
|      * repeatedly blocking and unblocking, invoking {@link
 | |
|      * #tryAcquire} until success.  This method can be used
 | |
|      * to implement method {@link Lock#lock}.
 | |
|      *
 | |
|      * @param arg the acquire argument.  This value is conveyed to
 | |
|      *        {@link #tryAcquire} but is otherwise uninterpreted and
 | |
|      *        can represent anything you like.
 | |
|      */
 | |
|     public final void acquire(long arg) {
 | |
|         if (!tryAcquire(arg) &&
 | |
|             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
 | |
|             selfInterrupt();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in exclusive mode, aborting if interrupted.
 | |
|      * Implemented by first checking interrupt status, then invoking
 | |
|      * at least once {@link #tryAcquire}, returning on
 | |
|      * success.  Otherwise the thread is queued, possibly repeatedly
 | |
|      * blocking and unblocking, invoking {@link #tryAcquire}
 | |
|      * until success or the thread is interrupted.  This method can be
 | |
|      * used to implement method {@link Lock#lockInterruptibly}.
 | |
|      *
 | |
|      * @param arg the acquire argument.  This value is conveyed to
 | |
|      *        {@link #tryAcquire} but is otherwise uninterpreted and
 | |
|      *        can represent anything you like.
 | |
|      * @throws InterruptedException if the current thread is interrupted
 | |
|      */
 | |
|     public final void acquireInterruptibly(long arg) throws InterruptedException {
 | |
|         if (Thread.interrupted())
 | |
|             throw new InterruptedException();
 | |
|         if (!tryAcquire(arg))
 | |
|             doAcquireInterruptibly(arg);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempts to acquire in exclusive mode, aborting if interrupted,
 | |
|      * and failing if the given timeout elapses.  Implemented by first
 | |
|      * checking interrupt status, then invoking at least once {@link
 | |
|      * #tryAcquire}, returning on success.  Otherwise, the thread is
 | |
|      * queued, possibly repeatedly blocking and unblocking, invoking
 | |
|      * {@link #tryAcquire} until success or the thread is interrupted
 | |
|      * or the timeout elapses.  This method can be used to implement
 | |
|      * method {@link Lock#tryLock(long, TimeUnit)}.
 | |
|      *
 | |
|      * @param arg the acquire argument.  This value is conveyed to
 | |
|      *        {@link #tryAcquire} but is otherwise uninterpreted and
 | |
|      *        can represent anything you like.
 | |
|      * @param nanosTimeout the maximum number of nanoseconds to wait
 | |
|      * @return {@code true} if acquired; {@code false} if timed out
 | |
|      * @throws InterruptedException if the current thread is interrupted
 | |
|      */
 | |
|     public final boolean tryAcquireNanos(long arg, long nanosTimeout) throws InterruptedException {
 | |
|         if (Thread.interrupted())
 | |
|             throw new InterruptedException();
 | |
|         return tryAcquire(arg) ||
 | |
|             doAcquireNanos(arg, nanosTimeout);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Releases in exclusive mode.  Implemented by unblocking one or
 | |
|      * more threads if {@link #tryRelease} returns true.
 | |
|      * This method can be used to implement method {@link Lock#unlock}.
 | |
|      *
 | |
|      * @param arg the release argument.  This value is conveyed to
 | |
|      *        {@link #tryRelease} but is otherwise uninterpreted and
 | |
|      *        can represent anything you like.
 | |
|      * @return the value returned from {@link #tryRelease}
 | |
|      */
 | |
|     public final boolean release(long arg) {
 | |
|         if (tryRelease(arg)) {
 | |
|             Node h = head;
 | |
|             if (h != null && h.waitStatus != 0)
 | |
|                 unparkSuccessor(h);
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in shared mode, ignoring interrupts.  Implemented by
 | |
|      * first invoking at least once {@link #tryAcquireShared},
 | |
|      * returning on success.  Otherwise the thread is queued, possibly
 | |
|      * repeatedly blocking and unblocking, invoking {@link
 | |
|      * #tryAcquireShared} until success.
 | |
|      *
 | |
|      * @param arg the acquire argument.  This value is conveyed to
 | |
|      *        {@link #tryAcquireShared} but is otherwise uninterpreted
 | |
|      *        and can represent anything you like.
 | |
|      */
 | |
|     public final void acquireShared(long arg) {
 | |
|         if (tryAcquireShared(arg) < 0)
 | |
|             doAcquireShared(arg);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Acquires in shared mode, aborting if interrupted.  Implemented
 | |
|      * by first checking interrupt status, then invoking at least once
 | |
|      * {@link #tryAcquireShared}, returning on success.  Otherwise the
 | |
|      * thread is queued, possibly repeatedly blocking and unblocking,
 | |
|      * invoking {@link #tryAcquireShared} until success or the thread
 | |
|      * is interrupted.
 | |
|      * @param arg the acquire argument.
 | |
|      * This value is conveyed to {@link #tryAcquireShared} but is
 | |
|      * otherwise uninterpreted and can represent anything
 | |
|      * you like.
 | |
|      * @throws InterruptedException if the current thread is interrupted
 | |
|      */
 | |
|     public final void acquireSharedInterruptibly(long arg) throws InterruptedException {
 | |
|         if (Thread.interrupted())
 | |
|             throw new InterruptedException();
 | |
|         if (tryAcquireShared(arg) < 0)
 | |
|             doAcquireSharedInterruptibly(arg);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Attempts to acquire in shared mode, aborting if interrupted, and
 | |
|      * failing if the given timeout elapses.  Implemented by first
 | |
|      * checking interrupt status, then invoking at least once {@link
 | |
|      * #tryAcquireShared}, returning on success.  Otherwise, the
 | |
|      * thread is queued, possibly repeatedly blocking and unblocking,
 | |
|      * invoking {@link #tryAcquireShared} until success or the thread
 | |
|      * is interrupted or the timeout elapses.
 | |
|      *
 | |
|      * @param arg the acquire argument.  This value is conveyed to
 | |
|      *        {@link #tryAcquireShared} but is otherwise uninterpreted
 | |
|      *        and can represent anything you like.
 | |
|      * @param nanosTimeout the maximum number of nanoseconds to wait
 | |
|      * @return {@code true} if acquired; {@code false} if timed out
 | |
|      * @throws InterruptedException if the current thread is interrupted
 | |
|      */
 | |
|     public final boolean tryAcquireSharedNanos(long arg, long nanosTimeout) throws InterruptedException {
 | |
|         if (Thread.interrupted())
 | |
|             throw new InterruptedException();
 | |
|         return tryAcquireShared(arg) >= 0 ||
 | |
|             doAcquireSharedNanos(arg, nanosTimeout);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Releases in shared mode.  Implemented by unblocking one or more
 | |
|      * threads if {@link #tryReleaseShared} returns true.
 | |
|      *
 | |
|      * @param arg the release argument.  This value is conveyed to
 | |
|      *        {@link #tryReleaseShared} but is otherwise uninterpreted
 | |
|      *        and can represent anything you like.
 | |
|      * @return the value returned from {@link #tryReleaseShared}
 | |
|      */
 | |
|     public final boolean releaseShared(long arg) {
 | |
|         if (tryReleaseShared(arg)) {
 | |
|             Node h = head;
 | |
|             if (h != null && h.waitStatus != 0)
 | |
|                 unparkSuccessor(h);
 | |
|             return true;
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     // Queue inspection methods
 | |
| 
 | |
|     /**
 | |
|      * Queries whether any threads are waiting to acquire. Note that
 | |
|      * because cancellations due to interrupts and timeouts may occur
 | |
|      * at any time, a {@code true} return does not guarantee that any
 | |
|      * other thread will ever acquire.
 | |
|      *
 | |
|      * <p>In this implementation, this operation returns in
 | |
|      * constant time.
 | |
|      *
 | |
|      * @return {@code true} if there may be other threads waiting to acquire
 | |
|      */
 | |
|     public final boolean hasQueuedThreads() {
 | |
|         return head != tail;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Queries whether any threads have ever contended to acquire this
 | |
|      * synchronizer; that is if an acquire method has ever blocked.
 | |
|      *
 | |
|      * <p>In this implementation, this operation returns in
 | |
|      * constant time.
 | |
|      *
 | |
|      * @return {@code true} if there has ever been contention
 | |
|      */
 | |
|     public final boolean hasContended() {
 | |
|         return head != null;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the first (longest-waiting) thread in the queue, or
 | |
|      * {@code null} if no threads are currently queued.
 | |
|      *
 | |
|      * <p>In this implementation, this operation normally returns in
 | |
|      * constant time, but may iterate upon contention if other threads are
 | |
|      * concurrently modifying the queue.
 | |
|      *
 | |
|      * @return the first (longest-waiting) thread in the queue, or
 | |
|      *         {@code null} if no threads are currently queued
 | |
|      */
 | |
|     public final Thread getFirstQueuedThread() {
 | |
|         // handle only fast path, else relay
 | |
|         return (head == tail)? null : fullGetFirstQueuedThread();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Version of getFirstQueuedThread called when fastpath fails
 | |
|      */
 | |
|     private Thread fullGetFirstQueuedThread() {
 | |
|         /*
 | |
|          * The first node is normally h.next. Try to get its
 | |
|          * thread field, ensuring consistent reads: If thread
 | |
|          * field is nulled out or s.prev is no longer head, then
 | |
|          * some other thread(s) concurrently performed setHead in
 | |
|          * between some of our reads. We try this twice before
 | |
|          * resorting to traversal.
 | |
|          */
 | |
|         Node h, s;
 | |
|         Thread st;
 | |
|         if (((h = head) != null && (s = h.next) != null &&
 | |
|              s.prev == head && (st = s.thread) != null) ||
 | |
|             ((h = head) != null && (s = h.next) != null &&
 | |
|              s.prev == head && (st = s.thread) != null))
 | |
|             return st;
 | |
| 
 | |
|         /*
 | |
|          * Head's next field might not have been set yet, or may have
 | |
|          * been unset after setHead. So we must check to see if tail
 | |
|          * is actually first node. If not, we continue on, safely
 | |
|          * traversing from tail back to head to find first,
 | |
|          * guaranteeing termination.
 | |
|          */
 | |
| 
 | |
|         Node t = tail;
 | |
|         Thread firstThread = null;
 | |
|         while (t != null && t != head) {
 | |
|             Thread tt = t.thread;
 | |
|             if (tt != null)
 | |
|                 firstThread = tt;
 | |
|             t = t.prev;
 | |
|         }
 | |
|         return firstThread;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns true if the given thread is currently queued.
 | |
|      *
 | |
|      * <p>This implementation traverses the queue to determine
 | |
|      * presence of the given thread.
 | |
|      *
 | |
|      * @param thread the thread
 | |
|      * @return {@code true} if the given thread is on the queue
 | |
|      * @throws NullPointerException if the thread is null
 | |
|      */
 | |
|     public final boolean isQueued(Thread thread) {
 | |
|         if (thread == null)
 | |
|             throw new NullPointerException();
 | |
|         for (Node p = tail; p != null; p = p.prev)
 | |
|             if (p.thread == thread)
 | |
|                 return true;
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return {@code true} if the apparent first queued thread, if one
 | |
|      * exists, is not waiting in exclusive mode. Used only as a heuristic
 | |
|      * in ReentrantReadWriteLock.
 | |
|      */
 | |
|     final boolean apparentlyFirstQueuedIsExclusive() {
 | |
|         Node h, s;
 | |
|         return ((h = head) != null && (s = h.next) != null &&
 | |
|                 s.nextWaiter != Node.SHARED);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Return {@code true} if the queue is empty or if the given thread
 | |
|      * is at the head of the queue. This is reliable only if
 | |
|      * <tt>current</tt> is actually Thread.currentThread() of caller.
 | |
|      */
 | |
|     final boolean isFirst(Thread current) {
 | |
|         Node h, s;
 | |
|         return ((h = head) == null ||
 | |
|                 ((s = h.next) != null && s.thread == current) ||
 | |
|                 fullIsFirst(current));
 | |
|     }
 | |
| 
 | |
|     final boolean fullIsFirst(Thread current) {
 | |
|         // same idea as fullGetFirstQueuedThread
 | |
|         Node h, s;
 | |
|         Thread firstThread = null;
 | |
|         if (((h = head) != null && (s = h.next) != null &&
 | |
|              s.prev == head && (firstThread = s.thread) != null))
 | |
|             return firstThread == current;
 | |
|         Node t = tail;
 | |
|         while (t != null && t != head) {
 | |
|             Thread tt = t.thread;
 | |
|             if (tt != null)
 | |
|                 firstThread = tt;
 | |
|             t = t.prev;
 | |
|         }
 | |
|         return firstThread == current || firstThread == null;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     // Instrumentation and monitoring methods
 | |
| 
 | |
|     /**
 | |
|      * Returns an estimate of the number of threads waiting to
 | |
|      * acquire.  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 system state, not for synchronization
 | |
|      * control.
 | |
|      *
 | |
|      * @return the estimated number of threads waiting to acquire
 | |
|      */
 | |
|     public final int getQueueLength() {
 | |
|         int n = 0;
 | |
|         for (Node p = tail; p != null; p = p.prev) {
 | |
|             if (p.thread != null)
 | |
|                 ++n;
 | |
|         }
 | |
|         return n;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a collection containing threads that may be waiting to
 | |
|      * acquire.  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
 | |
|      */
 | |
|     public final Collection<Thread> getQueuedThreads() {
 | |
|         ArrayList<Thread> list = new ArrayList<Thread>();
 | |
|         for (Node p = tail; p != null; p = p.prev) {
 | |
|             Thread t = p.thread;
 | |
|             if (t != null)
 | |
|                 list.add(t);
 | |
|         }
 | |
|         return list;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a collection containing threads that may be waiting to
 | |
|      * acquire in exclusive mode. This has the same properties
 | |
|      * as {@link #getQueuedThreads} except that it only returns
 | |
|      * those threads waiting due to an exclusive acquire.
 | |
|      *
 | |
|      * @return the collection of threads
 | |
|      */
 | |
|     public final Collection<Thread> getExclusiveQueuedThreads() {
 | |
|         ArrayList<Thread> list = new ArrayList<Thread>();
 | |
|         for (Node p = tail; p != null; p = p.prev) {
 | |
|             if (!p.isShared()) {
 | |
|                 Thread t = p.thread;
 | |
|                 if (t != null)
 | |
|                     list.add(t);
 | |
|             }
 | |
|         }
 | |
|         return list;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a collection containing threads that may be waiting to
 | |
|      * acquire in shared mode. This has the same properties
 | |
|      * as {@link #getQueuedThreads} except that it only returns
 | |
|      * those threads waiting due to a shared acquire.
 | |
|      *
 | |
|      * @return the collection of threads
 | |
|      */
 | |
|     public final Collection<Thread> getSharedQueuedThreads() {
 | |
|         ArrayList<Thread> list = new ArrayList<Thread>();
 | |
|         for (Node p = tail; p != null; p = p.prev) {
 | |
|             if (p.isShared()) {
 | |
|                 Thread t = p.thread;
 | |
|                 if (t != null)
 | |
|                     list.add(t);
 | |
|             }
 | |
|         }
 | |
|         return list;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a string identifying this synchronizer, as well as its state.
 | |
|      * The state, in brackets, includes the String {@code "State ="}
 | |
|      * followed by the current value of {@link #getState}, and either
 | |
|      * {@code "nonempty"} or {@code "empty"} depending on whether the
 | |
|      * queue is empty.
 | |
|      *
 | |
|      * @return a string identifying this synchronizer, as well as its state
 | |
|      */
 | |
|     public String toString() {
 | |
|         long s = getState();
 | |
|         String q  = hasQueuedThreads()? "non" : "";
 | |
|         return super.toString() +
 | |
|             "[State = " + s + ", " + q + "empty queue]";
 | |
|     }
 | |
| 
 | |
| 
 | |
|     // Internal support methods for Conditions
 | |
| 
 | |
|     /**
 | |
|      * Returns true if a node, always one that was initially placed on
 | |
|      * a condition queue, is now waiting to reacquire on sync queue.
 | |
|      * @param node the node
 | |
|      * @return true if is reacquiring
 | |
|      */
 | |
|     final boolean isOnSyncQueue(Node node) {
 | |
|         if (node.waitStatus == Node.CONDITION || node.prev == null)
 | |
|             return false;
 | |
|         if (node.next != null) // If has successor, it must be on queue
 | |
|             return true;
 | |
|         /*
 | |
|          * node.prev can be non-null, but not yet on queue because
 | |
|          * the CAS to place it on queue can fail. So we have to
 | |
|          * traverse from tail to make sure it actually made it.  It
 | |
|          * will always be near the tail in calls to this method, and
 | |
|          * unless the CAS failed (which is unlikely), it will be
 | |
|          * there, so we hardly ever traverse much.
 | |
|          */
 | |
|         return findNodeFromTail(node);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns true if node is on sync queue by searching backwards from tail.
 | |
|      * Called only when needed by isOnSyncQueue.
 | |
|      * @return true if present
 | |
|      */
 | |
|     private boolean findNodeFromTail(Node node) {
 | |
|         Node t = tail;
 | |
|         for (;;) {
 | |
|             if (t == node)
 | |
|                 return true;
 | |
|             if (t == null)
 | |
|                 return false;
 | |
|             t = t.prev;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Transfers a node from a condition queue onto sync queue.
 | |
|      * Returns true if successful.
 | |
|      * @param node the node
 | |
|      * @return true if successfully transferred (else the node was
 | |
|      * cancelled before signal).
 | |
|      */
 | |
|     final boolean transferForSignal(Node node) {
 | |
|         /*
 | |
|          * If cannot change waitStatus, the node has been cancelled.
 | |
|          */
 | |
|         if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
 | |
|             return false;
 | |
| 
 | |
|         /*
 | |
|          * Splice onto queue and try to set waitStatus of predecessor to
 | |
|          * indicate that thread is (probably) waiting. If cancelled or
 | |
|          * attempt to set waitStatus fails, wake up to resync (in which
 | |
|          * case the waitStatus can be transiently and harmlessly wrong).
 | |
|          */
 | |
|         Node p = enq(node);
 | |
|         int c = p.waitStatus;
 | |
|         if (c > 0 || !compareAndSetWaitStatus(p, c, Node.SIGNAL))
 | |
|             LockSupport.unpark(node.thread);
 | |
|         return true;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Transfers node, if necessary, to sync queue after a cancelled
 | |
|      * wait. Returns true if thread was cancelled before being
 | |
|      * signalled.
 | |
|      * @param current the waiting thread
 | |
|      * @param node its node
 | |
|      * @return true if cancelled before the node was signalled.
 | |
|      */
 | |
|     final boolean transferAfterCancelledWait(Node node) {
 | |
|         if (compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
 | |
|             enq(node);
 | |
|             return true;
 | |
|         }
 | |
|         /*
 | |
|          * If we lost out to a signal(), then we can't proceed
 | |
|          * until it finishes its enq().  Cancelling during an
 | |
|          * incomplete transfer is both rare and transient, so just
 | |
|          * spin.
 | |
|          */
 | |
|         while (!isOnSyncQueue(node))
 | |
|             Thread.yield();
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Invokes release with current state value; returns saved state.
 | |
|      * Cancels node and throws exception on failure.
 | |
|      * @param node the condition node for this wait
 | |
|      * @return previous sync state
 | |
|      */
 | |
|     final long fullyRelease(Node node) {
 | |
|         try {
 | |
|             long savedState = getState();
 | |
|             if (release(savedState))
 | |
|                 return savedState;
 | |
|         } catch (RuntimeException ex) {
 | |
|             node.waitStatus = Node.CANCELLED;
 | |
|             throw ex;
 | |
|         }
 | |
|         // reach here if release fails
 | |
|         node.waitStatus = Node.CANCELLED;
 | |
|         throw new IllegalMonitorStateException();
 | |
|     }
 | |
| 
 | |
|     // Instrumentation methods for conditions
 | |
| 
 | |
|     /**
 | |
|      * Queries whether the given ConditionObject
 | |
|      * uses this synchronizer as its lock.
 | |
|      *
 | |
|      * @param condition the condition
 | |
|      * @return <tt>true</tt> if owned
 | |
|      * @throws NullPointerException if the condition is null
 | |
|      */
 | |
|     public final boolean owns(ConditionObject condition) {
 | |
|         if (condition == null)
 | |
|             throw new NullPointerException();
 | |
|         return condition.isOwnedBy(this);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Queries whether any threads are waiting on the given condition
 | |
|      * associated with this synchronizer. 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 exclusive synchronization
 | |
|      *         is not held
 | |
|      * @throws IllegalArgumentException if the given condition is
 | |
|      *         not associated with this synchronizer
 | |
|      * @throws NullPointerException if the condition is null
 | |
|      */
 | |
|     public final boolean hasWaiters(ConditionObject condition) {
 | |
|         if (!owns(condition))
 | |
|             throw new IllegalArgumentException("Not owner");
 | |
|         return condition.hasWaiters();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns an estimate of the number of threads waiting on the
 | |
|      * given condition associated with this synchronizer. 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 exclusive synchronization
 | |
|      *         is not held
 | |
|      * @throws IllegalArgumentException if the given condition is
 | |
|      *         not associated with this synchronizer
 | |
|      * @throws NullPointerException if the condition is null
 | |
|      */
 | |
|     public final int getWaitQueueLength(ConditionObject condition) {
 | |
|         if (!owns(condition))
 | |
|             throw new IllegalArgumentException("Not owner");
 | |
|         return condition.getWaitQueueLength();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a collection containing those threads that may be
 | |
|      * waiting on the given condition associated with this
 | |
|      * synchronizer.  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.
 | |
|      *
 | |
|      * @param condition the condition
 | |
|      * @return the collection of threads
 | |
|      * @throws IllegalMonitorStateException if exclusive synchronization
 | |
|      *         is not held
 | |
|      * @throws IllegalArgumentException if the given condition is
 | |
|      *         not associated with this synchronizer
 | |
|      * @throws NullPointerException if the condition is null
 | |
|      */
 | |
|     public final Collection<Thread> getWaitingThreads(ConditionObject condition) {
 | |
|         if (!owns(condition))
 | |
|             throw new IllegalArgumentException("Not owner");
 | |
|         return condition.getWaitingThreads();
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Condition implementation for a {@link
 | |
|      * AbstractQueuedLongSynchronizer} serving as the basis of a {@link
 | |
|      * Lock} implementation.
 | |
|      *
 | |
|      * <p>Method documentation for this class describes mechanics,
 | |
|      * not behavioral specifications from the point of view of Lock
 | |
|      * and Condition users. Exported versions of this class will in
 | |
|      * general need to be accompanied by documentation describing
 | |
|      * condition semantics that rely on those of the associated
 | |
|      * <tt>AbstractQueuedLongSynchronizer</tt>.
 | |
|      *
 | |
|      * <p>This class is Serializable, but all fields are transient,
 | |
|      * so deserialized conditions have no waiters.
 | |
|      *
 | |
|      * @since 1.6
 | |
|      */
 | |
|     public class ConditionObject implements Condition, java.io.Serializable {
 | |
|         private static final long serialVersionUID = 1173984872572414699L;
 | |
|         /** First node of condition queue. */
 | |
|         private transient Node firstWaiter;
 | |
|         /** Last node of condition queue. */
 | |
|         private transient Node lastWaiter;
 | |
| 
 | |
|         /**
 | |
|          * Creates a new <tt>ConditionObject</tt> instance.
 | |
|          */
 | |
|         public ConditionObject() { }
 | |
| 
 | |
|         // Internal methods
 | |
| 
 | |
|         /**
 | |
|          * Adds a new waiter to wait queue.
 | |
|          * @return its new wait node
 | |
|          */
 | |
|         private Node addConditionWaiter() {
 | |
|             Node node = new Node(Thread.currentThread(), Node.CONDITION);
 | |
|             Node t = lastWaiter;
 | |
|             if (t == null)
 | |
|                 firstWaiter = node;
 | |
|             else
 | |
|                 t.nextWaiter = node;
 | |
|             lastWaiter = node;
 | |
|             return node;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Removes and transfers nodes until hit non-cancelled one or
 | |
|          * null. Split out from signal in part to encourage compilers
 | |
|          * to inline the case of no waiters.
 | |
|          * @param first (non-null) the first node on condition queue
 | |
|          */
 | |
|         private void doSignal(Node first) {
 | |
|             do {
 | |
|                 if ( (firstWaiter = first.nextWaiter) == null)
 | |
|                     lastWaiter = null;
 | |
|                 first.nextWaiter = null;
 | |
|             } while (!transferForSignal(first) &&
 | |
|                      (first = firstWaiter) != null);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Removes and transfers all nodes.
 | |
|          * @param first (non-null) the first node on condition queue
 | |
|          */
 | |
|         private void doSignalAll(Node first) {
 | |
|             lastWaiter = firstWaiter  = null;
 | |
|             do {
 | |
|                 Node next = first.nextWaiter;
 | |
|                 first.nextWaiter = null;
 | |
|                 transferForSignal(first);
 | |
|                 first = next;
 | |
|             } while (first != null);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns true if given node is on this condition queue.
 | |
|          * Call only when holding lock.
 | |
|          */
 | |
|         private boolean isOnConditionQueue(Node node) {
 | |
|             return node.next != null || node == lastWaiter;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Unlinks a cancelled waiter node from condition queue.  This
 | |
|          * is called when cancellation occurred during condition wait,
 | |
|          * not lock wait, and is called only after lock has been
 | |
|          * re-acquired by a cancelled waiter and the node is not known
 | |
|          * to already have been dequeued.  It is needed to avoid
 | |
|          * garbage retention in the absence of signals. So even though
 | |
|          * it may require a full traversal, it comes into play only
 | |
|          * when timeouts or cancellations occur in the absence of
 | |
|          * signals.
 | |
|          */
 | |
|         private void unlinkCancelledWaiter(Node node) {
 | |
|             Node t = firstWaiter;
 | |
|             Node trail = null;
 | |
|             while (t != null) {
 | |
|                 if (t == node) {
 | |
|                     Node next = t.nextWaiter;
 | |
|                     if (trail == null)
 | |
|                         firstWaiter = next;
 | |
|                     else
 | |
|                         trail.nextWaiter = next;
 | |
|                     if (lastWaiter == node)
 | |
|                         lastWaiter = trail;
 | |
|                     break;
 | |
|                 }
 | |
|                 trail = t;
 | |
|                 t = t.nextWaiter;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         // public methods
 | |
| 
 | |
|         /**
 | |
|          * Moves the longest-waiting thread, if one exists, from the
 | |
|          * wait queue for this condition to the wait queue for the
 | |
|          * owning lock.
 | |
|          *
 | |
|          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
 | |
|          *         returns {@code false}
 | |
|          */
 | |
|         public final void signal() {
 | |
|             if (!isHeldExclusively())
 | |
|                 throw new IllegalMonitorStateException();
 | |
|             Node first = firstWaiter;
 | |
|             if (first != null)
 | |
|                 doSignal(first);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Moves all threads from the wait queue for this condition to
 | |
|          * the wait queue for the owning lock.
 | |
|          *
 | |
|          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
 | |
|          *         returns {@code false}
 | |
|          */
 | |
|         public final void signalAll() {
 | |
|             if (!isHeldExclusively())
 | |
|                 throw new IllegalMonitorStateException();
 | |
|             Node first = firstWaiter;
 | |
|             if (first != null)
 | |
|                 doSignalAll(first);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Implements uninterruptible condition wait.
 | |
|          * <ol>
 | |
|          * <li> Save lock state returned by {@link #getState}
 | |
|          * <li> Invoke {@link #release} with
 | |
|          *      saved state as argument, throwing
 | |
|          *      IllegalMonitorStateException if it fails.
 | |
|          * <li> Block until signalled
 | |
|          * <li> Reacquire by invoking specialized version of
 | |
|          *      {@link #acquire} with saved state as argument.
 | |
|          * </ol>
 | |
|          */
 | |
|         public final void awaitUninterruptibly() {
 | |
|             Node node = addConditionWaiter();
 | |
|             long savedState = fullyRelease(node);
 | |
|             boolean interrupted = false;
 | |
|             while (!isOnSyncQueue(node)) {
 | |
|                 LockSupport.park(this);
 | |
|                 if (Thread.interrupted())
 | |
|                     interrupted = true;
 | |
|             }
 | |
|             if (acquireQueued(node, savedState) || interrupted)
 | |
|                 selfInterrupt();
 | |
|         }
 | |
| 
 | |
|         /*
 | |
|          * For interruptible waits, we need to track whether to throw
 | |
|          * InterruptedException, if interrupted while blocked on
 | |
|          * condition, versus reinterrupt current thread, if
 | |
|          * interrupted while blocked waiting to re-acquire.
 | |
|          */
 | |
| 
 | |
|         /** Mode meaning to reinterrupt on exit from wait */
 | |
|         private static final int REINTERRUPT =  1;
 | |
|         /** Mode meaning to throw InterruptedException on exit from wait */
 | |
|         private static final int THROW_IE    = -1;
 | |
| 
 | |
|         /**
 | |
|          * Checks for interrupt, returning THROW_IE if interrupted
 | |
|          * before signalled, REINTERRUPT if after signalled, or
 | |
|          * 0 if not interrupted.
 | |
|          */
 | |
|         private int checkInterruptWhileWaiting(Node node) {
 | |
|             return (Thread.interrupted()) ?
 | |
|                 ((transferAfterCancelledWait(node))? THROW_IE : REINTERRUPT) :
 | |
|                 0;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Throws InterruptedException, reinterrupts current thread, or
 | |
|          * does nothing, depending on mode.
 | |
|          */
 | |
|         private void reportInterruptAfterWait(int interruptMode)
 | |
|             throws InterruptedException {
 | |
|             if (interruptMode == THROW_IE)
 | |
|                 throw new InterruptedException();
 | |
|             else if (interruptMode == REINTERRUPT)
 | |
|                 selfInterrupt();
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Implements interruptible condition wait.
 | |
|          * <ol>
 | |
|          * <li> If current thread is interrupted, throw InterruptedException
 | |
|          * <li> Save lock state returned by {@link #getState}
 | |
|          * <li> Invoke {@link #release} with
 | |
|          *      saved state as argument, throwing
 | |
|          *      IllegalMonitorStateException  if it fails.
 | |
|          * <li> Block until signalled or interrupted
 | |
|          * <li> Reacquire by invoking specialized version of
 | |
|          *      {@link #acquire} with saved state as argument.
 | |
|          * <li> If interrupted while blocked in step 4, throw exception
 | |
|          * </ol>
 | |
|          */
 | |
|         public final void await() throws InterruptedException {
 | |
|             if (Thread.interrupted())
 | |
|                 throw new InterruptedException();
 | |
|             Node node = addConditionWaiter();
 | |
|             long savedState = fullyRelease(node);
 | |
|             int interruptMode = 0;
 | |
|             while (!isOnSyncQueue(node)) {
 | |
|                 LockSupport.park(this);
 | |
|                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
 | |
|                     break;
 | |
|             }
 | |
|             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
 | |
|                 interruptMode = REINTERRUPT;
 | |
|             if (isOnConditionQueue(node))
 | |
|                 unlinkCancelledWaiter(node);
 | |
|             if (interruptMode != 0)
 | |
|                 reportInterruptAfterWait(interruptMode);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Implements timed condition wait.
 | |
|          * <ol>
 | |
|          * <li> If current thread is interrupted, throw InterruptedException
 | |
|          * <li> Save lock state returned by {@link #getState}
 | |
|          * <li> Invoke {@link #release} with
 | |
|          *      saved state as argument, throwing
 | |
|          *      IllegalMonitorStateException  if it fails.
 | |
|          * <li> Block until signalled, interrupted, or timed out
 | |
|          * <li> Reacquire by invoking specialized version of
 | |
|          *      {@link #acquire} with saved state as argument.
 | |
|          * <li> If interrupted while blocked in step 4, throw InterruptedException
 | |
|          * </ol>
 | |
|          */
 | |
|         public final long awaitNanos(long nanosTimeout) throws InterruptedException {
 | |
|             if (Thread.interrupted())
 | |
|                 throw new InterruptedException();
 | |
|             Node node = addConditionWaiter();
 | |
|             long savedState = fullyRelease(node);
 | |
|             long lastTime = System.nanoTime();
 | |
|             int interruptMode = 0;
 | |
|             while (!isOnSyncQueue(node)) {
 | |
|                 if (nanosTimeout <= 0L) {
 | |
|                     transferAfterCancelledWait(node);
 | |
|                     break;
 | |
|                 }
 | |
|                 LockSupport.parkNanos(this, nanosTimeout);
 | |
|                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
 | |
|                     break;
 | |
| 
 | |
|                 long now = System.nanoTime();
 | |
|                 nanosTimeout -= now - lastTime;
 | |
|                 lastTime = now;
 | |
|             }
 | |
|             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
 | |
|                 interruptMode = REINTERRUPT;
 | |
|             if (isOnConditionQueue(node))
 | |
|                 unlinkCancelledWaiter(node);
 | |
|             if (interruptMode != 0)
 | |
|                 reportInterruptAfterWait(interruptMode);
 | |
|             return nanosTimeout - (System.nanoTime() - lastTime);
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Implements absolute timed condition wait.
 | |
|          * <ol>
 | |
|          * <li> If current thread is interrupted, throw InterruptedException
 | |
|          * <li> Save lock state returned by {@link #getState}
 | |
|          * <li> Invoke {@link #release} with
 | |
|          *      saved state as argument, throwing
 | |
|          *      IllegalMonitorStateException  if it fails.
 | |
|          * <li> Block until signalled, interrupted, or timed out
 | |
|          * <li> Reacquire by invoking specialized version of
 | |
|          *      {@link #acquire} with saved state as argument.
 | |
|          * <li> If interrupted while blocked in step 4, throw InterruptedException
 | |
|          * <li> If timed out while blocked in step 4, return false, else true
 | |
|          * </ol>
 | |
|          */
 | |
|         public final boolean awaitUntil(Date deadline) throws InterruptedException {
 | |
|             if (deadline == null)
 | |
|                 throw new NullPointerException();
 | |
|             long abstime = deadline.getTime();
 | |
|             if (Thread.interrupted())
 | |
|                 throw new InterruptedException();
 | |
|             Node node = addConditionWaiter();
 | |
|             long savedState = fullyRelease(node);
 | |
|             boolean timedout = false;
 | |
|             int interruptMode = 0;
 | |
|             while (!isOnSyncQueue(node)) {
 | |
|                 if (System.currentTimeMillis() > abstime) {
 | |
|                     timedout = transferAfterCancelledWait(node);
 | |
|                     break;
 | |
|                 }
 | |
|                 LockSupport.parkUntil(this, abstime);
 | |
|                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
 | |
|                     break;
 | |
|             }
 | |
|             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
 | |
|                 interruptMode = REINTERRUPT;
 | |
|             if (isOnConditionQueue(node))
 | |
|                 unlinkCancelledWaiter(node);
 | |
|             if (interruptMode != 0)
 | |
|                 reportInterruptAfterWait(interruptMode);
 | |
|             return !timedout;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Implements timed condition wait.
 | |
|          * <ol>
 | |
|          * <li> If current thread is interrupted, throw InterruptedException
 | |
|          * <li> Save lock state returned by {@link #getState}
 | |
|          * <li> Invoke {@link #release} with
 | |
|          *      saved state as argument, throwing
 | |
|          *      IllegalMonitorStateException  if it fails.
 | |
|          * <li> Block until signalled, interrupted, or timed out
 | |
|          * <li> Reacquire by invoking specialized version of
 | |
|          *      {@link #acquire} with saved state as argument.
 | |
|          * <li> If interrupted while blocked in step 4, throw InterruptedException
 | |
|          * <li> If timed out while blocked in step 4, return false, else true
 | |
|          * </ol>
 | |
|          */
 | |
|         public final boolean await(long time, TimeUnit unit) throws InterruptedException {
 | |
|             if (unit == null)
 | |
|                 throw new NullPointerException();
 | |
|             long nanosTimeout = unit.toNanos(time);
 | |
|             if (Thread.interrupted())
 | |
|                 throw new InterruptedException();
 | |
|             Node node = addConditionWaiter();
 | |
|             long savedState = fullyRelease(node);
 | |
|             long lastTime = System.nanoTime();
 | |
|             boolean timedout = false;
 | |
|             int interruptMode = 0;
 | |
|             while (!isOnSyncQueue(node)) {
 | |
|                 if (nanosTimeout <= 0L) {
 | |
|                     timedout = transferAfterCancelledWait(node);
 | |
|                     break;
 | |
|                 }
 | |
|                 LockSupport.parkNanos(this, nanosTimeout);
 | |
|                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
 | |
|                     break;
 | |
|                 long now = System.nanoTime();
 | |
|                 nanosTimeout -= now - lastTime;
 | |
|                 lastTime = now;
 | |
|             }
 | |
|             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
 | |
|                 interruptMode = REINTERRUPT;
 | |
|             if (isOnConditionQueue(node))
 | |
|                 unlinkCancelledWaiter(node);
 | |
|             if (interruptMode != 0)
 | |
|                 reportInterruptAfterWait(interruptMode);
 | |
|             return !timedout;
 | |
|         }
 | |
| 
 | |
|         //  support for instrumentation
 | |
| 
 | |
|         /**
 | |
|          * Returns true if this condition was created by the given
 | |
|          * synchronization object.
 | |
|          *
 | |
|          * @return {@code true} if owned
 | |
|          */
 | |
|         final boolean isOwnedBy(AbstractQueuedLongSynchronizer sync) {
 | |
|             return sync == AbstractQueuedLongSynchronizer.this;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Queries whether any threads are waiting on this condition.
 | |
|          * Implements {@link AbstractQueuedLongSynchronizer#hasWaiters}.
 | |
|          *
 | |
|          * @return {@code true} if there are any waiting threads
 | |
|          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
 | |
|          *         returns {@code false}
 | |
|          */
 | |
|         protected final boolean hasWaiters() {
 | |
|             if (!isHeldExclusively())
 | |
|                 throw new IllegalMonitorStateException();
 | |
|             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
 | |
|                 if (w.waitStatus == Node.CONDITION)
 | |
|                     return true;
 | |
|             }
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns an estimate of the number of threads waiting on
 | |
|          * this condition.
 | |
|          * Implements {@link AbstractQueuedLongSynchronizer#getWaitQueueLength}.
 | |
|          *
 | |
|          * @return the estimated number of waiting threads
 | |
|          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
 | |
|          *         returns {@code false}
 | |
|          */
 | |
|         protected final int getWaitQueueLength() {
 | |
|             if (!isHeldExclusively())
 | |
|                 throw new IllegalMonitorStateException();
 | |
|             int n = 0;
 | |
|             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
 | |
|                 if (w.waitStatus == Node.CONDITION)
 | |
|                     ++n;
 | |
|             }
 | |
|             return n;
 | |
|         }
 | |
| 
 | |
|         /**
 | |
|          * Returns a collection containing those threads that may be
 | |
|          * waiting on this Condition.
 | |
|          * Implements {@link AbstractQueuedLongSynchronizer#getWaitingThreads}.
 | |
|          *
 | |
|          * @return the collection of threads
 | |
|          * @throws IllegalMonitorStateException if {@link #isHeldExclusively}
 | |
|          *         returns {@code false}
 | |
|          */
 | |
|         protected final Collection<Thread> getWaitingThreads() {
 | |
|             if (!isHeldExclusively())
 | |
|                 throw new IllegalMonitorStateException();
 | |
|             ArrayList<Thread> list = new ArrayList<Thread>();
 | |
|             for (Node w = firstWaiter; w != null; w = w.nextWaiter) {
 | |
|                 if (w.waitStatus == Node.CONDITION) {
 | |
|                     Thread t = w.thread;
 | |
|                     if (t != null)
 | |
|                         list.add(t);
 | |
|                 }
 | |
|             }
 | |
|             return list;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Setup to support compareAndSet. We need to natively implement
 | |
|      * this here: For the sake of permitting future enhancements, we
 | |
|      * cannot explicitly subclass AtomicLong, which would be
 | |
|      * efficient and useful otherwise. So, as the lesser of evils, we
 | |
|      * natively implement using hotspot intrinsics API. And while we
 | |
|      * are at it, we do the same for other CASable fields (which could
 | |
|      * otherwise be done with atomic field updaters).
 | |
|      */
 | |
|     private static final Unsafe unsafe = Unsafe.getUnsafe();
 | |
|     private static final long stateOffset;
 | |
|     private static final long headOffset;
 | |
|     private static final long tailOffset;
 | |
|     private static final long waitStatusOffset;
 | |
| 
 | |
|     static {
 | |
|         try {
 | |
|             stateOffset = unsafe.objectFieldOffset
 | |
|                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
 | |
|             headOffset = unsafe.objectFieldOffset
 | |
|                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
 | |
|             tailOffset = unsafe.objectFieldOffset
 | |
|                 (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
 | |
|             waitStatusOffset = unsafe.objectFieldOffset
 | |
|                 (Node.class.getDeclaredField("waitStatus"));
 | |
| 
 | |
|         } catch (Exception ex) { throw new Error(ex); }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * CAS head field. Used only by enq
 | |
|      */
 | |
|     private final boolean compareAndSetHead(Node update) {
 | |
|         return unsafe.compareAndSwapObject(this, headOffset, null, update);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * CAS tail field. Used only by enq
 | |
|      */
 | |
|     private final boolean compareAndSetTail(Node expect, Node update) {
 | |
|         return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * CAS waitStatus field of a node.
 | |
|      */
 | |
|     private final static boolean compareAndSetWaitStatus(Node node,
 | |
|                                                          int expect,
 | |
|                                                          int update) {
 | |
|         return unsafe.compareAndSwapInt(node, waitStatusOffset,
 | |
|                                         expect, update);
 | |
|     }
 | |
| }
 |