1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.  Oracle designates this
7  * particular file as subject to the "Classpath" exception as provided
8  * by Oracle in the LICENSE file that accompanied this code.
9  *
10  * This code is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * version 2 for more details (a copy is included in the LICENSE file that
14  * accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License version
17  * 2 along with this work; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19  *
20  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21  * or visit www.oracle.com if you need additional information or have any
22  * questions.
23  */
24 
25 /*
26  * This file is available under and governed by the GNU General Public
27  * License version 2 only, as published by the Free Software Foundation.
28  * However, the following notice accompanied the original version of this
29  * file:
30  *
31  * Written by Doug Lea with assistance from members of JCP JSR-166
32  * Expert Group and released to the public domain, as explained at
33  * http://creativecommons.org/publicdomain/zero/1.0/
34  */
35 
36 package java.util.concurrent.locks;
37 
38 import java.util.concurrent.TimeUnit;
39 import jdk.internal.misc.Unsafe;
40 import jdk.internal.vm.annotation.ReservedStackAccess;
41 
42 /**
43  * A capability-based lock with three modes for controlling read/write
44  * access.  The state of a StampedLock consists of a version and mode.
45  * Lock acquisition methods return a stamp that represents and
46  * controls access with respect to a lock state; "try" versions of
47  * these methods may instead return the special value zero to
48  * represent failure to acquire access. Lock release and conversion
49  * methods require stamps as arguments, and fail if they do not match
50  * the state of the lock. The three modes are:
51  *
52  * <ul>
53  *
54  *  <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
55  *   waiting for exclusive access, returning a stamp that can be used
56  *   in method {@link #unlockWrite} to release the lock. Untimed and
57  *   timed versions of {@code tryWriteLock} are also provided. When
58  *   the lock is held in write mode, no read locks may be obtained,
59  *   and all optimistic read validations will fail.
60  *
61  *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
62  *   waiting for non-exclusive access, returning a stamp that can be
63  *   used in method {@link #unlockRead} to release the lock. Untimed
64  *   and timed versions of {@code tryReadLock} are also provided.
65  *
66  *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
67  *   returns a non-zero stamp only if the lock is not currently held in
68  *   write mode.  Method {@link #validate} returns true if the lock has not
69  *   been acquired in write mode since obtaining a given stamp, in which
70  *   case all actions prior to the most recent write lock release
71  *   happen-before actions following the call to {@code tryOptimisticRead}.
72  *   This mode can be thought of as an extremely weak version of a
73  *   read-lock, that can be broken by a writer at any time.  The use of
74  *   optimistic read mode for short read-only code segments often reduces
75  *   contention and improves throughput.  However, its use is inherently
76  *   fragile.  Optimistic read sections should only read fields and hold
77  *   them in local variables for later use after validation. Fields read
78  *   while in optimistic read mode may be wildly inconsistent, so usage
79  *   applies only when you are familiar enough with data representations to
80  *   check consistency and/or repeatedly invoke method {@code validate()}.
81  *   For example, such steps are typically required when first reading an
82  *   object or array reference, and then accessing one of its fields,
83  *   elements or methods.
84  *
85  * </ul>
86  *
87  * <p>This class also supports methods that conditionally provide
88  * conversions across the three modes. For example, method {@link
89  * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
90  * a valid write stamp if (1) already in writing mode (2) in reading
91  * mode and there are no other readers or (3) in optimistic read mode
92  * and the lock is available. The forms of these methods are designed to
93  * help reduce some of the code bloat that otherwise occurs in
94  * retry-based designs.
95  *
96  * <p>StampedLocks are designed for use as internal utilities in the
97  * development of thread-safe components. Their use relies on
98  * knowledge of the internal properties of the data, objects, and
99  * methods they are protecting.  They are not reentrant, so locked
100  * bodies should not call other unknown methods that may try to
101  * re-acquire locks (although you may pass a stamp to other methods
102  * that can use or convert it).  The use of read lock modes relies on
103  * the associated code sections being side-effect-free.  Unvalidated
104  * optimistic read sections cannot call methods that are not known to
105  * tolerate potential inconsistencies.  Stamps use finite
106  * representations, and are not cryptographically secure (i.e., a
107  * valid stamp may be guessable). Stamp values may recycle after (no
108  * sooner than) one year of continuous operation. A stamp held without
109  * use or validation for longer than this period may fail to validate
110  * correctly.  StampedLocks are serializable, but always deserialize
111  * into initial unlocked state, so they are not useful for remote
112  * locking.
113  *
114  * <p>Like {@link java.util.concurrent.Semaphore Semaphore}, but unlike most
115  * {@link Lock} implementations, StampedLocks have no notion of ownership.
116  * Locks acquired in one thread can be released or converted in another.
117  *
118  * <p>The scheduling policy of StampedLock does not consistently
119  * prefer readers over writers or vice versa.  All "try" methods are
120  * best-effort and do not necessarily conform to any scheduling or
121  * fairness policy. A zero return from any "try" method for acquiring
122  * or converting locks does not carry any information about the state
123  * of the lock; a subsequent invocation may succeed.
124  *
125  * <p>Because it supports coordinated usage across multiple lock
126  * modes, this class does not directly implement the {@link Lock} or
127  * {@link ReadWriteLock} interfaces. However, a StampedLock may be
128  * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link
129  * #asReadWriteLock()} in applications requiring only the associated
130  * set of functionality.
131  *
132  * <p><b>Memory Synchronization.</b> Methods with the effect of
133  * successfully locking in any mode have the same memory
134  * synchronization effects as a <em>Lock</em> action, as described in
135  * Chapter 17 of <cite>The Java Language Specification</cite>.
136  * Methods successfully unlocking in write mode have the same memory
137  * synchronization effects as an <em>Unlock</em> action.  In optimistic
138  * read usages, actions prior to the most recent write mode unlock action
139  * are guaranteed to happen-before those following a tryOptimisticRead
140  * only if a later validate returns true; otherwise there is no guarantee
141  * that the reads between tryOptimisticRead and validate obtain a
142  * consistent snapshot.
143  *
144  * <p><b>Sample Usage.</b> The following illustrates some usage idioms
145  * in a class that maintains simple two-dimensional points. The sample
146  * code illustrates some try/catch conventions even though they are
147  * not strictly needed here because no exceptions can occur in their
148  * bodies.
149  *
150  * <pre> {@code
151  * class Point {
152  *   private double x, y;
153  *   private final StampedLock sl = new StampedLock();
154  *
155  *   // an exclusively locked method
156  *   void move(double deltaX, double deltaY) {
157  *     long stamp = sl.writeLock();
158  *     try {
159  *       x += deltaX;
160  *       y += deltaY;
161  *     } finally {
162  *       sl.unlockWrite(stamp);
163  *     }
164  *   }
165  *
166  *   // a read-only method
167  *   // upgrade from optimistic read to read lock
168  *   double distanceFromOrigin() {
169  *     long stamp = sl.tryOptimisticRead();
170  *     try {
171  *       retryHoldingLock: for (;; stamp = sl.readLock()) {
172  *         if (stamp == 0L)
173  *           continue retryHoldingLock;
174  *         // possibly racy reads
175  *         double currentX = x;
176  *         double currentY = y;
177  *         if (!sl.validate(stamp))
178  *           continue retryHoldingLock;
179  *         return Math.hypot(currentX, currentY);
180  *       }
181  *     } finally {
182  *       if (StampedLock.isReadLockStamp(stamp))
183  *         sl.unlockRead(stamp);
184  *     }
185  *   }
186  *
187  *   // upgrade from optimistic read to write lock
188  *   void moveIfAtOrigin(double newX, double newY) {
189  *     long stamp = sl.tryOptimisticRead();
190  *     try {
191  *       retryHoldingLock: for (;; stamp = sl.writeLock()) {
192  *         if (stamp == 0L)
193  *           continue retryHoldingLock;
194  *         // possibly racy reads
195  *         double currentX = x;
196  *         double currentY = y;
197  *         if (!sl.validate(stamp))
198  *           continue retryHoldingLock;
199  *         if (currentX != 0.0 || currentY != 0.0)
200  *           break;
201  *         stamp = sl.tryConvertToWriteLock(stamp);
202  *         if (stamp == 0L)
203  *           continue retryHoldingLock;
204  *         // exclusive access
205  *         x = newX;
206  *         y = newY;
207  *         return;
208  *       }
209  *     } finally {
210  *       if (StampedLock.isWriteLockStamp(stamp))
211  *         sl.unlockWrite(stamp);
212  *     }
213  *   }
214  *
215  *   // Upgrade read lock to write lock
216  *   void moveIfAtOrigin(double newX, double newY) {
217  *     long stamp = sl.readLock();
218  *     try {
219  *       while (x == 0.0 && y == 0.0) {
220  *         long ws = sl.tryConvertToWriteLock(stamp);
221  *         if (ws != 0L) {
222  *           stamp = ws;
223  *           x = newX;
224  *           y = newY;
225  *           break;
226  *         }
227  *         else {
228  *           sl.unlockRead(stamp);
229  *           stamp = sl.writeLock();
230  *         }
231  *       }
232  *     } finally {
233  *       sl.unlock(stamp);
234  *     }
235  *   }
236  * }}</pre>
237  *
238  * @jls 17.4 Memory Model
239  * @since 1.8
240  * @author Doug Lea
241  */
242 public class StampedLock implements java.io.Serializable {
243     /*
244      * Algorithmic notes:
245      *
246      * The design employs elements of Sequence locks
247      * (as used in linux kernels; see Lameter's
248      * http://www.lameter.com/gelato2005.pdf
249      * and elsewhere; see
250      * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html)
251      * and Ordered RW locks (see Shirako et al
252      * http://dl.acm.org/citation.cfm?id=2312015)
253      *
254      * Conceptually, the primary state of the lock includes a sequence
255      * number that is odd when write-locked and even otherwise.
256      * However, this is offset by a reader count that is non-zero when
257      * read-locked.  The read count is ignored when validating
258      * "optimistic" seqlock-reader-style stamps.  Because we must use
259      * a small finite number of bits (currently 7) for readers, a
260      * supplementary reader overflow word is used when the number of
261      * readers exceeds the count field. We do this by treating the max
262      * reader count value (RBITS) as a spinlock protecting overflow
263      * updates.
264      *
265      * Waiters use a modified form of CLH lock used in
266      * AbstractQueuedSynchronizer (AQS; see its internal documentation
267      * for a fuller account), where each node is either a ReaderNode
268      * or WriterNode. Implementation of queued Writer mode is
269      * identical to AQS except for lock-state operations.  Sets of
270      * waiting readers are grouped (linked) under a common node (field
271      * cowaiters) so act as a single node with respect to most CLH
272      * mechanics.  This simplifies the scheduling policy to a
273      * mainly-FIFO scheme that incorporates elements of Phase-Fair
274      * locks (see Brandenburg & Anderson, especially
275      * http://www.cs.unc.edu/~bbb/diss/).  Method release does not
276      * itself wake up cowaiters. This is done by the primary thread,
277      * but helped by other cowaiters as they awaken.
278      *
279      * These rules apply to threads actually queued. Threads may also
280      * try to acquire locks before or in the process of enqueueing
281      * regardless of preference rules, and so may "barge" their way
282      * in.  Methods writeLock and readLock (but not the other variants
283      * of each) first unconditionally try to CAS state, falling back
284      * to test-and-test-and-set retries on failure, slightly shrinking
285      * race windows on initial attempts, thus making success more
286      * likely. Also, when some threads cancel (via interrupt or
287      * timeout), phase-fairness is at best roughly approximated.
288      *
289      * Nearly all of these mechanics are carried out in methods
290      * acquireWrite and acquireRead, that, as typical of such code,
291      * sprawl out because actions and retries rely on consistent sets
292      * of locally cached reads.
293      *
294      * For an explanation of the use of acquireFence, see
295      * http://gee.cs.oswego.edu/dl/html/j9mm.html as well as Boehm's
296      * paper (above). Note that sequence validation (mainly method
297      * validate()) requires stricter ordering rules than apply to
298      * normal volatile reads (of "state").  To ensure that writeLock
299      * acquisitions strictly precede subsequent writes in cases where
300      * this is not already forced, we use a storeStoreFence.
301      *
302      * The memory layout keeps lock state and queue pointers together
303      * (normally on the same cache line). This usually works well for
304      * read-mostly loads. In most other cases, the natural tendency of
305      * CLH locks to reduce memory contention lessens motivation to
306      * further spread out contended locations, but might be subject to
307      * future improvements.
308      */
309 
310     private static final long serialVersionUID = -6001602636862214147L;
311 
312     /** The number of bits to use for reader count before overflowing */
313     private static final int LG_READERS = 7; // 127 readers
314 
315     // Values for lock state and stamp operations
316     private static final long RUNIT = 1L;
317     private static final long WBIT  = 1L << LG_READERS;
318     private static final long RBITS = WBIT - 1L;
319     private static final long RFULL = RBITS - 1L;
320     private static final long ABITS = RBITS | WBIT;
321     private static final long SBITS = ~RBITS; // note overlap with ABITS
322     // not writing and conservatively non-overflowing
323     private static final long RSAFE = ~(3L << (LG_READERS - 1));
324 
325     /*
326      * 3 stamp modes can be distinguished by examining (m = stamp & ABITS):
327      * write mode: m == WBIT
328      * optimistic read mode: m == 0L (even when read lock is held)
329      * read mode: m > 0L && m <= RFULL (the stamp is a copy of state, but the
330      * read hold count in the stamp is unused other than to determine mode)
331      *
332      * This differs slightly from the encoding of state:
333      * (state & ABITS) == 0L indicates the lock is currently unlocked.
334      * (state & ABITS) == RBITS is a special transient value
335      * indicating spin-locked to manipulate reader bits overflow.
336      */
337 
338     /** Initial value for lock state; avoids failure value zero. */
339     private static final long ORIGIN = WBIT << 1;
340 
341     // Special value from cancelled acquire methods so caller can throw IE
342     private static final long INTERRUPTED = 1L;
343 
344     // Bits for Node.status
345     static final int WAITING   = 1;
346     static final int CANCELLED = 0x80000000; // must be negative
347 
348     /** CLH nodes */
349     abstract static class Node {
350         volatile Node prev;       // initially attached via casTail
351         volatile Node next;       // visibly nonnull when signallable
352         Thread waiter;            // visibly nonnull when enqueued
353         volatile int status;      // written by owner, atomic bit ops by others
354 
355         // methods for atomic operations
casPrev(Node c, Node v)356         final boolean casPrev(Node c, Node v) {  // for cleanQueue
357             return U.weakCompareAndSetReference(this, PREV, c, v);
358         }
casNext(Node c, Node v)359         final boolean casNext(Node c, Node v) {  // for cleanQueue
360             return U.weakCompareAndSetReference(this, NEXT, c, v);
361         }
getAndUnsetStatus(int v)362         final int getAndUnsetStatus(int v) {     // for signalling
363             return U.getAndBitwiseAndInt(this, STATUS, ~v);
364         }
setPrevRelaxed(Node p)365         final void setPrevRelaxed(Node p) {      // for off-queue assignment
366             U.putReference(this, PREV, p);
367         }
setStatusRelaxed(int s)368         final void setStatusRelaxed(int s) {     // for off-queue assignment
369             U.putInt(this, STATUS, s);
370         }
clearStatus()371         final void clearStatus() {               // for reducing unneeded signals
372             U.putIntOpaque(this, STATUS, 0);
373         }
374 
375         private static final long STATUS
376             = U.objectFieldOffset(Node.class, "status");
377         private static final long NEXT
378             = U.objectFieldOffset(Node.class, "next");
379         private static final long PREV
380             = U.objectFieldOffset(Node.class, "prev");
381     }
382 
383     static final class WriterNode extends Node { // node for writers
384     }
385 
386     static final class ReaderNode extends Node { // node for readers
387         volatile ReaderNode cowaiters;           // list of linked readers
casCowaiters(ReaderNode c, ReaderNode v)388         final boolean casCowaiters(ReaderNode c, ReaderNode v) {
389             return U.weakCompareAndSetReference(this, COWAITERS, c, v);
390         }
setCowaitersRelaxed(ReaderNode p)391         final void setCowaitersRelaxed(ReaderNode p) {
392             U.putReference(this, COWAITERS, p);
393         }
394         private static final long COWAITERS
395             = U.objectFieldOffset(ReaderNode.class, "cowaiters");
396     }
397 
398     /** Head of CLH queue */
399     private transient volatile Node head;
400     /** Tail (last) of CLH queue */
401     private transient volatile Node tail;
402 
403     // views
404     transient ReadLockView readLockView;
405     transient WriteLockView writeLockView;
406     transient ReadWriteLockView readWriteLockView;
407 
408     /** Lock sequence/state */
409     private transient volatile long state;
410     /** extra reader count when state read count saturated */
411     private transient int readerOverflow;
412 
413     /**
414      * Creates a new lock, initially in unlocked state.
415      */
StampedLock()416     public StampedLock() {
417         state = ORIGIN;
418     }
419 
420     // internal lock methods
421 
casState(long expect, long update)422     private boolean casState(long expect, long update) {
423         return U.compareAndSetLong(this, STATE, expect, update);
424     }
425 
426     @ReservedStackAccess
tryAcquireWrite()427     private long tryAcquireWrite() {
428         long s, nextState;
429         if (((s = state) & ABITS) == 0L && casState(s, nextState = s | WBIT)) {
430             U.storeStoreFence();
431             return nextState;
432         }
433         return 0L;
434     }
435 
436     @ReservedStackAccess
tryAcquireRead()437     private long tryAcquireRead() {
438         for (long s, m, nextState;;) {
439             if ((m = (s = state) & ABITS) < RFULL) {
440                 if (casState(s, nextState = s + RUNIT))
441                     return nextState;
442             }
443             else if (m == WBIT)
444                 return 0L;
445             else if ((nextState = tryIncReaderOverflow(s)) != 0L)
446                 return nextState;
447         }
448     }
449 
450     /**
451      * Returns an unlocked state, incrementing the version and
452      * avoiding special failure value 0L.
453      *
454      * @param s a write-locked state (or stamp)
455      */
unlockWriteState(long s)456     private static long unlockWriteState(long s) {
457         return ((s += WBIT) == 0L) ? ORIGIN : s;
458     }
459 
releaseWrite(long s)460     private long releaseWrite(long s) {
461         long nextState = state = unlockWriteState(s);
462         signalNext(head);
463         return nextState;
464     }
465 
466     /**
467      * Exclusively acquires the lock, blocking if necessary
468      * until available.
469      *
470      * @return a write stamp that can be used to unlock or convert mode
471      */
472     @ReservedStackAccess
writeLock()473     public long writeLock() {
474         // try unconditional CAS confirming weak read
475         long s = U.getLongOpaque(this, STATE) & ~ABITS, nextState;
476         if (casState(s, nextState = s | WBIT)) {
477             U.storeStoreFence();
478             return nextState;
479         }
480         return acquireWrite(false, false, 0L);
481     }
482 
483     /**
484      * Exclusively acquires the lock if it is immediately available.
485      *
486      * @return a write stamp that can be used to unlock or convert mode,
487      * or zero if the lock is not available
488      */
tryWriteLock()489     public long tryWriteLock() {
490         return tryAcquireWrite();
491     }
492 
493     /**
494      * Exclusively acquires the lock if it is available within the
495      * given time and the current thread has not been interrupted.
496      * Behavior under timeout and interruption matches that specified
497      * for method {@link Lock#tryLock(long,TimeUnit)}.
498      *
499      * @param time the maximum time to wait for the lock
500      * @param unit the time unit of the {@code time} argument
501      * @return a write stamp that can be used to unlock or convert mode,
502      * or zero if the lock is not available
503      * @throws InterruptedException if the current thread is interrupted
504      * before acquiring the lock
505      */
tryWriteLock(long time, TimeUnit unit)506     public long tryWriteLock(long time, TimeUnit unit)
507         throws InterruptedException {
508         long nanos = unit.toNanos(time);
509         if (!Thread.interrupted()) {
510             long nextState;
511             if ((nextState = tryAcquireWrite()) != 0L)
512                 return nextState;
513             if (nanos <= 0L)
514                 return 0L;
515             nextState = acquireWrite(true, true, System.nanoTime() + nanos);
516             if (nextState != INTERRUPTED)
517                 return nextState;
518         }
519         throw new InterruptedException();
520     }
521 
522     /**
523      * Exclusively acquires the lock, blocking if necessary
524      * until available or the current thread is interrupted.
525      * Behavior under interruption matches that specified
526      * for method {@link Lock#lockInterruptibly()}.
527      *
528      * @return a write stamp that can be used to unlock or convert mode
529      * @throws InterruptedException if the current thread is interrupted
530      * before acquiring the lock
531      */
writeLockInterruptibly()532     public long writeLockInterruptibly() throws InterruptedException {
533         long nextState;
534         if (!Thread.interrupted() &&
535             ((nextState = tryAcquireWrite()) != 0L ||
536              (nextState = acquireWrite(true, false, 0L)) != INTERRUPTED))
537             return nextState;
538         throw new InterruptedException();
539     }
540 
541     /**
542      * Non-exclusively acquires the lock, blocking if necessary
543      * until available.
544      *
545      * @return a read stamp that can be used to unlock or convert mode
546      */
547     @ReservedStackAccess
readLock()548     public long readLock() {
549         // unconditionally optimistically try non-overflow case once
550         long s = U.getLongOpaque(this, STATE) & RSAFE, nextState;
551         if (casState(s, nextState = s + RUNIT))
552             return nextState;
553         else
554             return acquireRead(false, false, 0L);
555     }
556 
557     /**
558      * Non-exclusively acquires the lock if it is immediately available.
559      *
560      * @return a read stamp that can be used to unlock or convert mode,
561      * or zero if the lock is not available
562      */
tryReadLock()563     public long tryReadLock() {
564         return tryAcquireRead();
565     }
566 
567     /**
568      * Non-exclusively acquires the lock if it is available within the
569      * given time and the current thread has not been interrupted.
570      * Behavior under timeout and interruption matches that specified
571      * for method {@link Lock#tryLock(long,TimeUnit)}.
572      *
573      * @param time the maximum time to wait for the lock
574      * @param unit the time unit of the {@code time} argument
575      * @return a read stamp that can be used to unlock or convert mode,
576      * or zero if the lock is not available
577      * @throws InterruptedException if the current thread is interrupted
578      * before acquiring the lock
579      */
tryReadLock(long time, TimeUnit unit)580     public long tryReadLock(long time, TimeUnit unit)
581         throws InterruptedException {
582         long nanos = unit.toNanos(time);
583         if (!Thread.interrupted()) {
584             long nextState;
585             if (tail == head && (nextState = tryAcquireRead()) != 0L)
586                 return nextState;
587             if (nanos <= 0L)
588                 return 0L;
589             nextState = acquireRead(true, true, System.nanoTime() + nanos);
590             if (nextState != INTERRUPTED)
591                 return nextState;
592         }
593         throw new InterruptedException();
594     }
595 
596     /**
597      * Non-exclusively acquires the lock, blocking if necessary
598      * until available or the current thread is interrupted.
599      * Behavior under interruption matches that specified
600      * for method {@link Lock#lockInterruptibly()}.
601      *
602      * @return a read stamp that can be used to unlock or convert mode
603      * @throws InterruptedException if the current thread is interrupted
604      * before acquiring the lock
605      */
readLockInterruptibly()606     public long readLockInterruptibly() throws InterruptedException {
607         long nextState;
608         if (!Thread.interrupted() &&
609             ((nextState = tryAcquireRead()) != 0L ||
610              (nextState = acquireRead(true, false, 0L)) != INTERRUPTED))
611             return nextState;
612         throw new InterruptedException();
613     }
614 
615     /**
616      * Returns a stamp that can later be validated, or zero
617      * if exclusively locked.
618      *
619      * @return a valid optimistic read stamp, or zero if exclusively locked
620      */
tryOptimisticRead()621     public long tryOptimisticRead() {
622         long s;
623         return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
624     }
625 
626     /**
627      * Returns true if the lock has not been exclusively acquired
628      * since issuance of the given stamp. Always returns false if the
629      * stamp is zero. Always returns true if the stamp represents a
630      * currently held lock. Invoking this method with a value not
631      * obtained from {@link #tryOptimisticRead} or a locking method
632      * for this lock has no defined effect or result.
633      *
634      * @param stamp a stamp
635      * @return {@code true} if the lock has not been exclusively acquired
636      * since issuance of the given stamp; else false
637      */
validate(long stamp)638     public boolean validate(long stamp) {
639         U.loadFence();
640         return (stamp & SBITS) == (state & SBITS);
641     }
642 
643     /**
644      * If the lock state matches the given stamp, releases the
645      * exclusive lock.
646      *
647      * @param stamp a stamp returned by a write-lock operation
648      * @throws IllegalMonitorStateException if the stamp does
649      * not match the current state of this lock
650      */
651     @ReservedStackAccess
unlockWrite(long stamp)652     public void unlockWrite(long stamp) {
653         if (state != stamp || (stamp & WBIT) == 0L)
654             throw new IllegalMonitorStateException();
655         releaseWrite(stamp);
656     }
657 
658     /**
659      * If the lock state matches the given stamp, releases the
660      * non-exclusive lock.
661      *
662      * @param stamp a stamp returned by a read-lock operation
663      * @throws IllegalMonitorStateException if the stamp does
664      * not match the current state of this lock
665      */
666     @ReservedStackAccess
unlockRead(long stamp)667     public void unlockRead(long stamp) {
668         long s, m;
669         if ((stamp & RBITS) != 0L) {
670             while (((s = state) & SBITS) == (stamp & SBITS) &&
671                    ((m = s & RBITS) != 0L)) {
672                 if (m < RFULL) {
673                     if (casState(s, s - RUNIT)) {
674                         if (m == RUNIT)
675                             signalNext(head);
676                         return;
677                     }
678                 }
679                 else if (tryDecReaderOverflow(s) != 0L)
680                     return;
681             }
682         }
683         throw new IllegalMonitorStateException();
684     }
685 
686     /**
687      * If the lock state matches the given stamp, releases the
688      * corresponding mode of the lock.
689      *
690      * @param stamp a stamp returned by a lock operation
691      * @throws IllegalMonitorStateException if the stamp does
692      * not match the current state of this lock
693      */
unlock(long stamp)694     public void unlock(long stamp) {
695         if ((stamp & WBIT) != 0L)
696             unlockWrite(stamp);
697         else
698             unlockRead(stamp);
699     }
700 
701     /**
702      * If the lock state matches the given stamp, atomically performs one of
703      * the following actions. If the stamp represents holding a write
704      * lock, returns it.  Or, if a read lock, if the write lock is
705      * available, releases the read lock and returns a write stamp.
706      * Or, if an optimistic read, returns a write stamp only if
707      * immediately available. This method returns zero in all other
708      * cases.
709      *
710      * @param stamp a stamp
711      * @return a valid write stamp, or zero on failure
712      */
tryConvertToWriteLock(long stamp)713     public long tryConvertToWriteLock(long stamp) {
714         long a = stamp & ABITS, m, s, nextState;
715         while (((s = state) & SBITS) == (stamp & SBITS)) {
716             if ((m = s & ABITS) == 0L) {
717                 if (a != 0L)
718                     break;
719                 if (casState(s, nextState = s | WBIT)) {
720                     U.storeStoreFence();
721                     return nextState;
722                 }
723             } else if (m == WBIT) {
724                 if (a != m)
725                     break;
726                 return stamp;
727             } else if (m == RUNIT && a != 0L) {
728                 if (casState(s, nextState = s - RUNIT + WBIT))
729                     return nextState;
730             } else
731                 break;
732         }
733         return 0L;
734     }
735 
736     /**
737      * If the lock state matches the given stamp, atomically performs one of
738      * the following actions. If the stamp represents holding a write
739      * lock, releases it and obtains a read lock.  Or, if a read lock,
740      * returns it. Or, if an optimistic read, acquires a read lock and
741      * returns a read stamp only if immediately available. This method
742      * returns zero in all other cases.
743      *
744      * @param stamp a stamp
745      * @return a valid read stamp, or zero on failure
746      */
tryConvertToReadLock(long stamp)747     public long tryConvertToReadLock(long stamp) {
748         long a, s, nextState;
749         while (((s = state) & SBITS) == (stamp & SBITS)) {
750             if ((a = stamp & ABITS) >= WBIT) {
751                 if (s != stamp) // write stamp
752                     break;
753                 nextState = state = unlockWriteState(s) + RUNIT;
754                 signalNext(head);
755                 return nextState;
756             } else if (a == 0L) { // optimistic read stamp
757                 if ((s & ABITS) < RFULL) {
758                     if (casState(s, nextState = s + RUNIT))
759                         return nextState;
760                 } else if ((nextState = tryIncReaderOverflow(s)) != 0L)
761                     return nextState;
762             } else { // already a read stamp
763                 if ((s & ABITS) == 0L)
764                     break;
765                 return stamp;
766             }
767         }
768         return 0L;
769     }
770 
771     /**
772      * If the lock state matches the given stamp then, atomically, if the stamp
773      * represents holding a lock, releases it and returns an
774      * observation stamp.  Or, if an optimistic read, returns it if
775      * validated. This method returns zero in all other cases, and so
776      * may be useful as a form of "tryUnlock".
777      *
778      * @param stamp a stamp
779      * @return a valid optimistic read stamp, or zero on failure
780      */
tryConvertToOptimisticRead(long stamp)781     public long tryConvertToOptimisticRead(long stamp) {
782         long a, m, s, nextState;
783         U.loadFence();
784         while (((s = state) & SBITS) == (stamp & SBITS)) {
785             if ((a = stamp & ABITS) >= WBIT) {
786                 if (s != stamp)   // write stamp
787                     break;
788                 return releaseWrite(s);
789             } else if (a == 0L) { // already an optimistic read stamp
790                 return stamp;
791             } else if ((m = s & ABITS) == 0L) { // invalid read stamp
792                 break;
793             } else if (m < RFULL) {
794                 if (casState(s, nextState = s - RUNIT)) {
795                     if (m == RUNIT)
796                         signalNext(head);
797                     return nextState & SBITS;
798                 }
799             } else if ((nextState = tryDecReaderOverflow(s)) != 0L)
800                 return nextState & SBITS;
801         }
802         return 0L;
803     }
804 
805     /**
806      * Releases the write lock if it is held, without requiring a
807      * stamp value. This method may be useful for recovery after
808      * errors.
809      *
810      * @return {@code true} if the lock was held, else false
811      */
812     @ReservedStackAccess
tryUnlockWrite()813     public boolean tryUnlockWrite() {
814         long s;
815         if (((s = state) & WBIT) != 0L) {
816             releaseWrite(s);
817             return true;
818         }
819         return false;
820     }
821 
822     /**
823      * Releases one hold of the read lock if it is held, without
824      * requiring a stamp value. This method may be useful for recovery
825      * after errors.
826      *
827      * @return {@code true} if the read lock was held, else false
828      */
829     @ReservedStackAccess
tryUnlockRead()830     public boolean tryUnlockRead() {
831         long s, m;
832         while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
833             if (m < RFULL) {
834                 if (casState(s, s - RUNIT)) {
835                     if (m == RUNIT)
836                         signalNext(head);
837                     return true;
838                 }
839             }
840             else if (tryDecReaderOverflow(s) != 0L)
841                 return true;
842         }
843         return false;
844     }
845 
846     // status monitoring methods
847 
848     /**
849      * Returns combined state-held and overflow read count for given
850      * state s.
851      */
getReadLockCount(long s)852     private int getReadLockCount(long s) {
853         long readers;
854         if ((readers = s & RBITS) >= RFULL)
855             readers = RFULL + readerOverflow;
856         return (int) readers;
857     }
858 
859     /**
860      * Returns {@code true} if the lock is currently held exclusively.
861      *
862      * @return {@code true} if the lock is currently held exclusively
863      */
isWriteLocked()864     public boolean isWriteLocked() {
865         return (state & WBIT) != 0L;
866     }
867 
868     /**
869      * Returns {@code true} if the lock is currently held non-exclusively.
870      *
871      * @return {@code true} if the lock is currently held non-exclusively
872      */
isReadLocked()873     public boolean isReadLocked() {
874         return (state & RBITS) != 0L;
875     }
876 
877     /**
878      * Tells whether a stamp represents holding a lock exclusively.
879      * This method may be useful in conjunction with
880      * {@link #tryConvertToWriteLock}, for example: <pre> {@code
881      * long stamp = sl.tryOptimisticRead();
882      * try {
883      *   ...
884      *   stamp = sl.tryConvertToWriteLock(stamp);
885      *   ...
886      * } finally {
887      *   if (StampedLock.isWriteLockStamp(stamp))
888      *     sl.unlockWrite(stamp);
889      * }}</pre>
890      *
891      * @param stamp a stamp returned by a previous StampedLock operation
892      * @return {@code true} if the stamp was returned by a successful
893      *   write-lock operation
894      * @since 10
895      */
isWriteLockStamp(long stamp)896     public static boolean isWriteLockStamp(long stamp) {
897         return (stamp & ABITS) == WBIT;
898     }
899 
900     /**
901      * Tells whether a stamp represents holding a lock non-exclusively.
902      * This method may be useful in conjunction with
903      * {@link #tryConvertToReadLock}, for example: <pre> {@code
904      * long stamp = sl.tryOptimisticRead();
905      * try {
906      *   ...
907      *   stamp = sl.tryConvertToReadLock(stamp);
908      *   ...
909      * } finally {
910      *   if (StampedLock.isReadLockStamp(stamp))
911      *     sl.unlockRead(stamp);
912      * }}</pre>
913      *
914      * @param stamp a stamp returned by a previous StampedLock operation
915      * @return {@code true} if the stamp was returned by a successful
916      *   read-lock operation
917      * @since 10
918      */
isReadLockStamp(long stamp)919     public static boolean isReadLockStamp(long stamp) {
920         return (stamp & RBITS) != 0L;
921     }
922 
923     /**
924      * Tells whether a stamp represents holding a lock.
925      * This method may be useful in conjunction with
926      * {@link #tryConvertToReadLock} and {@link #tryConvertToWriteLock},
927      * for example: <pre> {@code
928      * long stamp = sl.tryOptimisticRead();
929      * try {
930      *   ...
931      *   stamp = sl.tryConvertToReadLock(stamp);
932      *   ...
933      *   stamp = sl.tryConvertToWriteLock(stamp);
934      *   ...
935      * } finally {
936      *   if (StampedLock.isLockStamp(stamp))
937      *     sl.unlock(stamp);
938      * }}</pre>
939      *
940      * @param stamp a stamp returned by a previous StampedLock operation
941      * @return {@code true} if the stamp was returned by a successful
942      *   read-lock or write-lock operation
943      * @since 10
944      */
isLockStamp(long stamp)945     public static boolean isLockStamp(long stamp) {
946         return (stamp & ABITS) != 0L;
947     }
948 
949     /**
950      * Tells whether a stamp represents a successful optimistic read.
951      *
952      * @param stamp a stamp returned by a previous StampedLock operation
953      * @return {@code true} if the stamp was returned by a successful
954      *   optimistic read operation, that is, a non-zero return from
955      *   {@link #tryOptimisticRead()} or
956      *   {@link #tryConvertToOptimisticRead(long)}
957      * @since 10
958      */
isOptimisticReadStamp(long stamp)959     public static boolean isOptimisticReadStamp(long stamp) {
960         return (stamp & ABITS) == 0L && stamp != 0L;
961     }
962 
963     /**
964      * Queries the number of read locks held for this lock. This
965      * method is designed for use in monitoring system state, not for
966      * synchronization control.
967      * @return the number of read locks held
968      */
getReadLockCount()969     public int getReadLockCount() {
970         return getReadLockCount(state);
971     }
972 
973     /**
974      * Returns a string identifying this lock, as well as its lock
975      * state.  The state, in brackets, includes the String {@code
976      * "Unlocked"} or the String {@code "Write-locked"} or the String
977      * {@code "Read-locks:"} followed by the current number of
978      * read-locks held.
979      *
980      * @return a string identifying this lock, as well as its lock state
981      */
toString()982     public String toString() {
983         long s = state;
984         return super.toString() +
985             ((s & ABITS) == 0L ? "[Unlocked]" :
986              (s & WBIT) != 0L ? "[Write-locked]" :
987              "[Read-locks:" + getReadLockCount(s) + "]");
988     }
989 
990     // views
991 
992     /**
993      * Returns a plain {@link Lock} view of this StampedLock in which
994      * the {@link Lock#lock} method is mapped to {@link #readLock},
995      * and similarly for other methods. The returned Lock does not
996      * support a {@link Condition}; method {@link Lock#newCondition()}
997      * throws {@code UnsupportedOperationException}.
998      *
999      * @return the lock
1000      */
asReadLock()1001     public Lock asReadLock() {
1002         ReadLockView v;
1003         if ((v = readLockView) != null) return v;
1004         return readLockView = new ReadLockView();
1005     }
1006 
1007     /**
1008      * Returns a plain {@link Lock} view of this StampedLock in which
1009      * the {@link Lock#lock} method is mapped to {@link #writeLock},
1010      * and similarly for other methods. The returned Lock does not
1011      * support a {@link Condition}; method {@link Lock#newCondition()}
1012      * throws {@code UnsupportedOperationException}.
1013      *
1014      * @return the lock
1015      */
asWriteLock()1016     public Lock asWriteLock() {
1017         WriteLockView v;
1018         if ((v = writeLockView) != null) return v;
1019         return writeLockView = new WriteLockView();
1020     }
1021 
1022     /**
1023      * Returns a {@link ReadWriteLock} view of this StampedLock in
1024      * which the {@link ReadWriteLock#readLock()} method is mapped to
1025      * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to
1026      * {@link #asWriteLock()}.
1027      *
1028      * @return the lock
1029      */
asReadWriteLock()1030     public ReadWriteLock asReadWriteLock() {
1031         ReadWriteLockView v;
1032         if ((v = readWriteLockView) != null) return v;
1033         return readWriteLockView = new ReadWriteLockView();
1034     }
1035 
1036     // view classes
1037 
1038     final class ReadLockView implements Lock {
lock()1039         public void lock() { readLock(); }
lockInterruptibly()1040         public void lockInterruptibly() throws InterruptedException {
1041             readLockInterruptibly();
1042         }
tryLock()1043         public boolean tryLock() { return tryReadLock() != 0L; }
tryLock(long time, TimeUnit unit)1044         public boolean tryLock(long time, TimeUnit unit)
1045             throws InterruptedException {
1046             return tryReadLock(time, unit) != 0L;
1047         }
unlock()1048         public void unlock() { unstampedUnlockRead(); }
newCondition()1049         public Condition newCondition() {
1050             throw new UnsupportedOperationException();
1051         }
1052     }
1053 
1054     final class WriteLockView implements Lock {
lock()1055         public void lock() { writeLock(); }
lockInterruptibly()1056         public void lockInterruptibly() throws InterruptedException {
1057             writeLockInterruptibly();
1058         }
tryLock()1059         public boolean tryLock() { return tryWriteLock() != 0L; }
tryLock(long time, TimeUnit unit)1060         public boolean tryLock(long time, TimeUnit unit)
1061             throws InterruptedException {
1062             return tryWriteLock(time, unit) != 0L;
1063         }
unlock()1064         public void unlock() { unstampedUnlockWrite(); }
newCondition()1065         public Condition newCondition() {
1066             throw new UnsupportedOperationException();
1067         }
1068     }
1069 
1070     final class ReadWriteLockView implements ReadWriteLock {
readLock()1071         public Lock readLock() { return asReadLock(); }
writeLock()1072         public Lock writeLock() { return asWriteLock(); }
1073     }
1074 
1075     // Unlock methods without stamp argument checks for view classes.
1076     // Needed because view-class lock methods throw away stamps.
1077 
unstampedUnlockWrite()1078     final void unstampedUnlockWrite() {
1079         long s;
1080         if (((s = state) & WBIT) == 0L)
1081             throw new IllegalMonitorStateException();
1082         releaseWrite(s);
1083     }
1084 
unstampedUnlockRead()1085     final void unstampedUnlockRead() {
1086         long s, m;
1087         while ((m = (s = state) & RBITS) > 0L) {
1088             if (m < RFULL) {
1089                 if (casState(s, s - RUNIT)) {
1090                     if (m == RUNIT)
1091                         signalNext(head);
1092                     return;
1093                 }
1094             }
1095             else if (tryDecReaderOverflow(s) != 0L)
1096                 return;
1097         }
1098         throw new IllegalMonitorStateException();
1099     }
1100 
readObject(java.io.ObjectInputStream s)1101     private void readObject(java.io.ObjectInputStream s)
1102         throws java.io.IOException, ClassNotFoundException {
1103         s.defaultReadObject();
1104         state = ORIGIN; // reset to unlocked state
1105     }
1106 
1107     // overflow handling methods
1108 
1109     /**
1110      * Tries to increment readerOverflow by first setting state
1111      * access bits value to RBITS, indicating hold of spinlock,
1112      * then updating, then releasing.
1113      *
1114      * @param s a reader overflow stamp: (s & ABITS) >= RFULL
1115      * @return new stamp on success, else zero
1116      */
tryIncReaderOverflow(long s)1117     private long tryIncReaderOverflow(long s) {
1118         // assert (s & ABITS) >= RFULL;
1119         if ((s & ABITS) != RFULL)
1120             Thread.onSpinWait();
1121         else if (casState(s, s | RBITS)) {
1122             ++readerOverflow;
1123             return state = s;
1124         }
1125         return 0L;
1126     }
1127 
1128     /**
1129      * Tries to decrement readerOverflow.
1130      *
1131      * @param s a reader overflow stamp: (s & ABITS) >= RFULL
1132      * @return new stamp on success, else zero
1133      */
tryDecReaderOverflow(long s)1134     private long tryDecReaderOverflow(long s) {
1135         // assert (s & ABITS) >= RFULL;
1136         if ((s & ABITS) != RFULL)
1137             Thread.onSpinWait();
1138         else if (casState(s, s | RBITS)) {
1139             int r; long nextState;
1140             if ((r = readerOverflow) > 0) {
1141                 readerOverflow = r - 1;
1142                 nextState = s;
1143             }
1144             else
1145                 nextState = s - RUNIT;
1146             return state = nextState;
1147         }
1148         return 0L;
1149     }
1150 
1151     // release methods
1152 
1153     /**
1154      * Wakes up the successor of given node, if one exists, and unsets its
1155      * WAITING status to avoid park race. This may fail to wake up an
1156      * eligible thread when one or more have been cancelled, but
1157      * cancelAcquire ensures liveness.
1158      */
signalNext(Node h)1159     static final void signalNext(Node h) {
1160         Node s;
1161         if (h != null && (s = h.next) != null && s.status > 0) {
1162             s.getAndUnsetStatus(WAITING);
1163             LockSupport.unpark(s.waiter);
1164         }
1165     }
1166 
1167     /**
1168      * Removes and unparks all cowaiters of node, if it exists.
1169      */
signalCowaiters(ReaderNode node)1170     private static void signalCowaiters(ReaderNode node) {
1171         if (node != null) {
1172             for (ReaderNode c; (c = node.cowaiters) != null; ) {
1173                 if (node.casCowaiters(c, c.cowaiters))
1174                     LockSupport.unpark(c.waiter);
1175             }
1176         }
1177     }
1178 
1179     // queue link methods
casTail(Node c, Node v)1180     private boolean casTail(Node c, Node v) {
1181         return U.compareAndSetReference(this, TAIL, c, v);
1182     }
1183 
1184     /** tries once to CAS a new dummy node for head */
tryInitializeHead()1185     private void tryInitializeHead() {
1186         Node h = new WriterNode();
1187         if (U.compareAndSetReference(this, HEAD, null, h))
1188             tail = h;
1189     }
1190 
1191     /**
1192      * For explanation, see above and AbstractQueuedSynchronizer
1193      * internal documentation.
1194      *
1195      * @param interruptible true if should check interrupts and if so
1196      * return INTERRUPTED
1197      * @param timed if true use timed waits
1198      * @param time the System.nanoTime value to timeout at (and return zero)
1199      * @return next state, or INTERRUPTED
1200      */
acquireWrite(boolean interruptible, boolean timed, long time)1201     private long acquireWrite(boolean interruptible, boolean timed, long time) {
1202         byte spins = 0, postSpins = 0;   // retries upon unpark of first thread
1203         boolean interrupted = false, first = false;
1204         WriterNode node = null;
1205         Node pred = null;
1206         for (long s, nextState;;) {
1207             if (!first && (pred = (node == null) ? null : node.prev) != null &&
1208                 !(first = (head == pred))) {
1209                 if (pred.status < 0) {
1210                     cleanQueue();           // predecessor cancelled
1211                     continue;
1212                 } else if (pred.prev == null) {
1213                     Thread.onSpinWait();    // ensure serialization
1214                     continue;
1215                 }
1216             }
1217             if ((first || pred == null) && ((s = state) & ABITS) == 0L &&
1218                 casState(s, nextState = s | WBIT)) {
1219                 U.storeStoreFence();
1220                 if (first) {
1221                     node.prev = null;
1222                     head = node;
1223                     pred.next = null;
1224                     node.waiter = null;
1225                     if (interrupted)
1226                         Thread.currentThread().interrupt();
1227                 }
1228                 return nextState;
1229             } else if (node == null) {          // retry before enqueuing
1230                 node = new WriterNode();
1231             } else if (pred == null) {          // try to enqueue
1232                 Node t = tail;
1233                 node.setPrevRelaxed(t);
1234                 if (t == null)
1235                     tryInitializeHead();
1236                 else if (!casTail(t, node))
1237                     node.setPrevRelaxed(null);  // back out
1238                 else
1239                     t.next = node;
1240             } else if (first && spins != 0) {   // reduce unfairness
1241                 --spins;
1242                 Thread.onSpinWait();
1243             } else if (node.status == 0) {      // enable signal
1244                 if (node.waiter == null)
1245                     node.waiter = Thread.currentThread();
1246                 node.status = WAITING;
1247             } else {
1248                 long nanos;
1249                 spins = postSpins = (byte)((postSpins << 1) | 1);
1250                 if (!timed)
1251                     LockSupport.park(this);
1252                 else if ((nanos = time - System.nanoTime()) > 0L)
1253                     LockSupport.parkNanos(this, nanos);
1254                 else
1255                     break;
1256                 node.clearStatus();
1257                 if ((interrupted |= Thread.interrupted()) && interruptible)
1258                     break;
1259             }
1260         }
1261         return cancelAcquire(node, interrupted);
1262     }
1263 
1264     /**
1265      * See above for explanation.
1266      *
1267      * @param interruptible true if should check interrupts and if so
1268      * return INTERRUPTED
1269      * @param timed if true use timed waits
1270      * @param time the System.nanoTime value to timeout at (and return zero)
1271      * @return next state, or INTERRUPTED
1272      */
acquireRead(boolean interruptible, boolean timed, long time)1273     private long acquireRead(boolean interruptible, boolean timed, long time) {
1274         boolean interrupted = false;
1275         ReaderNode node = null;
1276         /*
1277          * Loop:
1278          *   if empty, try to acquire
1279          *   if tail is Reader, try to cowait; restart if leader stale or cancels
1280          *   else try to create and enqueue node, and wait in 2nd loop below
1281          */
1282         for (;;) {
1283             ReaderNode leader; long nextState;
1284             Node tailPred = null, t = tail;
1285             if ((t == null || (tailPred = t.prev) == null) &&
1286                 (nextState = tryAcquireRead()) != 0L) // try now if empty
1287                 return nextState;
1288             else if (t == null)
1289                 tryInitializeHead();
1290             else if (tailPred == null || !(t instanceof ReaderNode)) {
1291                 if (node == null)
1292                     node = new ReaderNode();
1293                 if (tail == t) {
1294                     node.setPrevRelaxed(t);
1295                     if (casTail(t, node)) {
1296                         t.next = node;
1297                         break; // node is leader; wait in loop below
1298                     }
1299                     node.setPrevRelaxed(null);
1300                 }
1301             } else if ((leader = (ReaderNode)t) == tail) { // try to cowait
1302                 for (boolean attached = false;;) {
1303                     if (leader.status < 0 || leader.prev == null)
1304                         break;
1305                     else if (node == null)
1306                         node = new ReaderNode();
1307                     else if (node.waiter == null)
1308                         node.waiter = Thread.currentThread();
1309                     else if (!attached) {
1310                         ReaderNode c = leader.cowaiters;
1311                         node.setCowaitersRelaxed(c);
1312                         attached = leader.casCowaiters(c, node);
1313                         if (!attached)
1314                             node.setCowaitersRelaxed(null);
1315                     } else {
1316                         long nanos = 0L;
1317                         if (!timed)
1318                             LockSupport.park(this);
1319                         else if ((nanos = time - System.nanoTime()) > 0L)
1320                             LockSupport.parkNanos(this, nanos);
1321                         interrupted |= Thread.interrupted();
1322                         if ((interrupted && interruptible) ||
1323                             (timed && nanos <= 0L))
1324                             return cancelCowaiter(node, leader, interrupted);
1325                     }
1326                 }
1327                 if (node != null)
1328                     node.waiter = null;
1329                 long ns = tryAcquireRead();
1330                 signalCowaiters(leader);
1331                 if (interrupted)
1332                     Thread.currentThread().interrupt();
1333                 if (ns != 0L)
1334                     return ns;
1335                 else
1336                     node = null; // restart if stale, missed, or leader cancelled
1337             }
1338         }
1339 
1340         // node is leader of a cowait group; almost same as acquireWrite
1341         byte spins = 0, postSpins = 0;   // retries upon unpark of first thread
1342         boolean first = false;
1343         Node pred = null;
1344         for (long nextState;;) {
1345             if (!first && (pred = node.prev) != null &&
1346                 !(first = (head == pred))) {
1347                 if (pred.status < 0) {
1348                     cleanQueue();           // predecessor cancelled
1349                     continue;
1350                 } else if (pred.prev == null) {
1351                     Thread.onSpinWait();    // ensure serialization
1352                     continue;
1353                 }
1354             }
1355             if ((first || pred == null) &&
1356                 (nextState = tryAcquireRead()) != 0L) {
1357                 if (first) {
1358                     node.prev = null;
1359                     head = node;
1360                     pred.next = null;
1361                     node.waiter = null;
1362                 }
1363                 signalCowaiters(node);
1364                 if (interrupted)
1365                     Thread.currentThread().interrupt();
1366                 return nextState;
1367             } else if (first && spins != 0) {
1368                 --spins;
1369                 Thread.onSpinWait();
1370             } else if (node.status == 0) {
1371                 if (node.waiter == null)
1372                     node.waiter = Thread.currentThread();
1373                 node.status = WAITING;
1374             } else {
1375                 long nanos;
1376                 spins = postSpins = (byte)((postSpins << 1) | 1);
1377                 if (!timed)
1378                     LockSupport.park(this);
1379                 else if ((nanos = time - System.nanoTime()) > 0L)
1380                     LockSupport.parkNanos(this, nanos);
1381                 else
1382                     break;
1383                 node.clearStatus();
1384                 if ((interrupted |= Thread.interrupted()) && interruptible)
1385                     break;
1386             }
1387         }
1388         return cancelAcquire(node, interrupted);
1389     }
1390 
1391     // Cancellation support
1392 
1393     /**
1394      * Possibly repeatedly traverses from tail, unsplicing cancelled
1395      * nodes until none are found. Unparks nodes that may have been
1396      * relinked to be next eligible acquirer.
1397      */
cleanQueue()1398     private void cleanQueue() {
1399         for (;;) {                               // restart point
1400             for (Node q = tail, s = null, p, n;;) { // (p, q, s) triples
1401                 if (q == null || (p = q.prev) == null)
1402                     return;                      // end of list
1403                 if (s == null ? tail != q : (s.prev != q || s.status < 0))
1404                     break;                       // inconsistent
1405                 if (q.status < 0) {              // cancelled
1406                     if ((s == null ? casTail(q, p) : s.casPrev(q, p)) &&
1407                         q.prev == p) {
1408                         p.casNext(q, s);         // OK if fails
1409                         if (p.prev == null)
1410                             signalNext(p);
1411                     }
1412                     break;
1413                 }
1414                 if ((n = p.next) != q) {         // help finish
1415                     if (n != null && q.prev == p && q.status >= 0) {
1416                         p.casNext(n, q);
1417                         if (p.prev == null)
1418                             signalNext(p);
1419                     }
1420                     break;
1421                 }
1422                 s = q;
1423                 q = q.prev;
1424             }
1425         }
1426     }
1427 
1428     /**
1429      * If leader exists, possibly repeatedly traverses cowaiters,
1430      * unsplicing the given cancelled node until not found.
1431      */
unlinkCowaiter(ReaderNode node, ReaderNode leader)1432     private void unlinkCowaiter(ReaderNode node, ReaderNode leader) {
1433         if (leader != null) {
1434             while (leader.prev != null && leader.status >= 0) {
1435                 for (ReaderNode p = leader, q; ; p = q) {
1436                     if ((q = p.cowaiters) == null)
1437                         return;
1438                     if (q == node) {
1439                         p.casCowaiters(q, q.cowaiters);
1440                         break;  // recheck even if succeeded
1441                     }
1442                 }
1443             }
1444         }
1445     }
1446 
1447     /**
1448      * If node non-null, forces cancel status and unsplices it from
1449      * queue, wakes up any cowaiters, and possibly wakes up successor
1450      * to recheck status.
1451      *
1452      * @param node the waiter (may be null if not yet enqueued)
1453      * @param interrupted if already interrupted
1454      * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
1455      */
cancelAcquire(Node node, boolean interrupted)1456     private long cancelAcquire(Node node, boolean interrupted) {
1457         if (node != null) {
1458             node.waiter = null;
1459             node.status = CANCELLED;
1460             cleanQueue();
1461             if (node instanceof ReaderNode)
1462                 signalCowaiters((ReaderNode)node);
1463         }
1464         return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1465     }
1466 
1467     /**
1468      * If node non-null, forces cancel status and unsplices from
1469      * leader's cowaiters list unless/until it is also cancelled.
1470      *
1471      * @param node if non-null, the waiter
1472      * @param leader if non-null, the node heading cowaiters list
1473      * @param interrupted if already interrupted
1474      * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
1475      */
cancelCowaiter(ReaderNode node, ReaderNode leader, boolean interrupted)1476     private long cancelCowaiter(ReaderNode node, ReaderNode leader,
1477                                 boolean interrupted) {
1478         if (node != null) {
1479             node.waiter = null;
1480             node.status = CANCELLED;
1481             unlinkCowaiter(node, leader);
1482         }
1483         return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1484     }
1485 
1486     // Unsafe
1487     private static final Unsafe U = Unsafe.getUnsafe();
1488     private static final long STATE
1489         = U.objectFieldOffset(StampedLock.class, "state");
1490     private static final long HEAD
1491         = U.objectFieldOffset(StampedLock.class, "head");
1492     private static final long TAIL
1493         = U.objectFieldOffset(StampedLock.class, "tail");
1494 
1495     static {
1496         Class<?> ensureLoaded = LockSupport.class;
1497     }
1498 }
1499