• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.lang.invoke.MethodHandles;
39 import java.lang.invoke.VarHandle;
40 import java.util.concurrent.TimeUnit;
41 import jdk.internal.vm.annotation.ReservedStackAccess;
42 
43 /**
44  * A capability-based lock with three modes for controlling read/write
45  * access.  The state of a StampedLock consists of a version and mode.
46  * Lock acquisition methods return a stamp that represents and
47  * controls access with respect to a lock state; "try" versions of
48  * these methods may instead return the special value zero to
49  * represent failure to acquire access. Lock release and conversion
50  * methods require stamps as arguments, and fail if they do not match
51  * the state of the lock. The three modes are:
52  *
53  * <ul>
54  *
55  *  <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
56  *   waiting for exclusive access, returning a stamp that can be used
57  *   in method {@link #unlockWrite} to release the lock. Untimed and
58  *   timed versions of {@code tryWriteLock} are also provided. When
59  *   the lock is held in write mode, no read locks may be obtained,
60  *   and all optimistic read validations will fail.
61  *
62  *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
63  *   waiting for non-exclusive access, returning a stamp that can be
64  *   used in method {@link #unlockRead} to release the lock. Untimed
65  *   and timed versions of {@code tryReadLock} are also provided.
66  *
67  *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
68  *   returns a non-zero stamp only if the lock is not currently held
69  *   in write mode. Method {@link #validate} returns true if the lock
70  *   has not been acquired in write mode since obtaining a given
71  *   stamp.  This mode can be thought of as an extremely weak version
72  *   of a read-lock, that can be broken by a writer at any time.  The
73  *   use of optimistic mode for short read-only code segments often
74  *   reduces contention and improves throughput.  However, its use is
75  *   inherently fragile.  Optimistic read sections should only read
76  *   fields and hold them in local variables for later use after
77  *   validation. Fields read while in optimistic mode may be wildly
78  *   inconsistent, so usage applies only when you are familiar enough
79  *   with data representations to check consistency and/or repeatedly
80  *   invoke method {@code validate()}.  For example, such steps are
81  *   typically required when first reading an object or array
82  *   reference, and then accessing one of its fields, elements or
83  *   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 mode and
92  * 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>Sample Usage.</b> The following illustrates some usage idioms
133  * in a class that maintains simple two-dimensional points. The sample
134  * code illustrates some try/catch conventions even though they are
135  * not strictly needed here because no exceptions can occur in their
136  * bodies.
137  *
138  * <pre> {@code
139  * class Point {
140  *   private double x, y;
141  *   private final StampedLock sl = new StampedLock();
142  *
143  *   // an exclusively locked method
144  *   void move(double deltaX, double deltaY) {
145  *     long stamp = sl.writeLock();
146  *     try {
147  *       x += deltaX;
148  *       y += deltaY;
149  *     } finally {
150  *       sl.unlockWrite(stamp);
151  *     }
152  *   }
153  *
154  *   // a read-only method
155  *   // upgrade from optimistic read to read lock
156  *   double distanceFromOrigin() {
157  *     long stamp = sl.tryOptimisticRead();
158  *     try {
159  *       retryHoldingLock: for (;; stamp = sl.readLock()) {
160  *         if (stamp == 0L)
161  *           continue retryHoldingLock;
162  *         // possibly racy reads
163  *         double currentX = x;
164  *         double currentY = y;
165  *         if (!sl.validate(stamp))
166  *           continue retryHoldingLock;
167  *         return Math.hypot(currentX, currentY);
168  *       }
169  *     } finally {
170  *       if (StampedLock.isReadLockStamp(stamp))
171  *         sl.unlockRead(stamp);
172  *     }
173  *   }
174  *
175  *   // upgrade from optimistic read to write lock
176  *   void moveIfAtOrigin(double newX, double newY) {
177  *     long stamp = sl.tryOptimisticRead();
178  *     try {
179  *       retryHoldingLock: for (;; stamp = sl.writeLock()) {
180  *         if (stamp == 0L)
181  *           continue retryHoldingLock;
182  *         // possibly racy reads
183  *         double currentX = x;
184  *         double currentY = y;
185  *         if (!sl.validate(stamp))
186  *           continue retryHoldingLock;
187  *         if (currentX != 0.0 || currentY != 0.0)
188  *           break;
189  *         stamp = sl.tryConvertToWriteLock(stamp);
190  *         if (stamp == 0L)
191  *           continue retryHoldingLock;
192  *         // exclusive access
193  *         x = newX;
194  *         y = newY;
195  *         return;
196  *       }
197  *     } finally {
198  *       if (StampedLock.isWriteLockStamp(stamp))
199  *         sl.unlockWrite(stamp);
200  *     }
201  *   }
202  *
203  *   // Upgrade read lock to write lock
204  *   void moveIfAtOrigin(double newX, double newY) {
205  *     long stamp = sl.readLock();
206  *     try {
207  *       while (x == 0.0 && y == 0.0) {
208  *         long ws = sl.tryConvertToWriteLock(stamp);
209  *         if (ws != 0L) {
210  *           stamp = ws;
211  *           x = newX;
212  *           y = newY;
213  *           break;
214  *         }
215  *         else {
216  *           sl.unlockRead(stamp);
217  *           stamp = sl.writeLock();
218  *         }
219  *       }
220  *     } finally {
221  *       sl.unlock(stamp);
222  *     }
223  *   }
224  * }}</pre>
225  *
226  * @since 1.8
227  * @author Doug Lea
228  */
229 public class StampedLock implements java.io.Serializable {
230     /*
231      * Algorithmic notes:
232      *
233      * The design employs elements of Sequence locks
234      * (as used in linux kernels; see Lameter's
235      * http://www.lameter.com/gelato2005.pdf
236      * and elsewhere; see
237      * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html)
238      * and Ordered RW locks (see Shirako et al
239      * http://dl.acm.org/citation.cfm?id=2312015)
240      *
241      * Conceptually, the primary state of the lock includes a sequence
242      * number that is odd when write-locked and even otherwise.
243      * However, this is offset by a reader count that is non-zero when
244      * read-locked.  The read count is ignored when validating
245      * "optimistic" seqlock-reader-style stamps.  Because we must use
246      * a small finite number of bits (currently 7) for readers, a
247      * supplementary reader overflow word is used when the number of
248      * readers exceeds the count field. We do this by treating the max
249      * reader count value (RBITS) as a spinlock protecting overflow
250      * updates.
251      *
252      * Waiters use a modified form of CLH lock used in
253      * AbstractQueuedSynchronizer (see its internal documentation for
254      * a fuller account), where each node is tagged (field mode) as
255      * either a reader or writer. Sets of waiting readers are grouped
256      * (linked) under a common node (field cowait) so act as a single
257      * node with respect to most CLH mechanics.  By virtue of the
258      * queue structure, wait nodes need not actually carry sequence
259      * numbers; we know each is greater than its predecessor.  This
260      * simplifies the scheduling policy to a mainly-FIFO scheme that
261      * incorporates elements of Phase-Fair locks (see Brandenburg &
262      * Anderson, especially http://www.cs.unc.edu/~bbb/diss/).  In
263      * particular, we use the phase-fair anti-barging rule: If an
264      * incoming reader arrives while read lock is held but there is a
265      * queued writer, this incoming reader is queued.  (This rule is
266      * responsible for some of the complexity of method acquireRead,
267      * but without it, the lock becomes highly unfair.) Method release
268      * does not (and sometimes cannot) itself wake up cowaiters. This
269      * is done by the primary thread, but helped by any other threads
270      * with nothing better to do in methods acquireRead and
271      * acquireWrite.
272      *
273      * These rules apply to threads actually queued. All tryLock forms
274      * opportunistically try to acquire locks regardless of preference
275      * rules, and so may "barge" their way in.  Randomized spinning is
276      * used in the acquire methods to reduce (increasingly expensive)
277      * context switching while also avoiding sustained memory
278      * thrashing among many threads.  We limit spins to the head of
279      * queue. If, upon wakening, a thread fails to obtain lock, and is
280      * still (or becomes) the first waiting thread (which indicates
281      * that some other thread barged and obtained lock), it escalates
282      * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
283      * continually losing to barging threads.
284      *
285      * Nearly all of these mechanics are carried out in methods
286      * acquireWrite and acquireRead, that, as typical of such code,
287      * sprawl out because actions and retries rely on consistent sets
288      * of locally cached reads.
289      *
290      * As noted in Boehm's paper (above), sequence validation (mainly
291      * method validate()) requires stricter ordering rules than apply
292      * to normal volatile reads (of "state").  To force orderings of
293      * reads before a validation and the validation itself in those
294      * cases where this is not already forced, we use acquireFence.
295      * Unlike in that paper, we allow writers to use plain writes.
296      * One would not expect reorderings of such writes with the lock
297      * acquisition CAS because there is a "control dependency", but it
298      * is theoretically possible, so we additionally add a
299      * storeStoreFence after lock acquisition CAS.
300      *
301      * ----------------------------------------------------------------
302      * Here's an informal proof that plain reads by _successful_
303      * readers see plain writes from preceding but not following
304      * writers (following Boehm and the C++ standard [atomics.fences]):
305      *
306      * Because of the total synchronization order of accesses to
307      * volatile long state containing the sequence number, writers and
308      * _successful_ readers can be globally sequenced.
309      *
310      * int x, y;
311      *
312      * Writer 1:
313      * inc sequence (odd - "locked")
314      * storeStoreFence();
315      * x = 1; y = 2;
316      * inc sequence (even - "unlocked")
317      *
318      * Successful Reader:
319      * read sequence (even)
320      * // must see writes from Writer 1 but not Writer 2
321      * r1 = x; r2 = y;
322      * acquireFence();
323      * read sequence (even - validated unchanged)
324      * // use r1 and r2
325      *
326      * Writer 2:
327      * inc sequence (odd - "locked")
328      * storeStoreFence();
329      * x = 3; y = 4;
330      * inc sequence (even - "unlocked")
331      *
332      * Visibility of writer 1's stores is normal - reader's initial
333      * read of state synchronizes with writer 1's final write to state.
334      * Lack of visibility of writer 2's plain writes is less obvious.
335      * If reader's read of x or y saw writer 2's write, then (assuming
336      * semantics of C++ fences) the storeStoreFence would "synchronize"
337      * with reader's acquireFence and reader's validation read must see
338      * writer 2's initial write to state and so validation must fail.
339      * But making this "proof" formal and rigorous is an open problem!
340      * ----------------------------------------------------------------
341      *
342      * The memory layout keeps lock state and queue pointers together
343      * (normally on the same cache line). This usually works well for
344      * read-mostly loads. In most other cases, the natural tendency of
345      * adaptive-spin CLH locks to reduce memory contention lessens
346      * motivation to further spread out contended locations, but might
347      * be subject to future improvements.
348      */
349 
350     private static final long serialVersionUID = -6001602636862214147L;
351 
352     /** Number of processors, for spin control */
353     private static final int NCPU = Runtime.getRuntime().availableProcessors();
354 
355     /** Maximum number of retries before enqueuing on acquisition; at least 1 */
356     private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
357 
358     /** Maximum number of tries before blocking at head on acquisition */
359     private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 1;
360 
361     /** Maximum number of retries before re-blocking */
362     private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 1;
363 
364     /** The period for yielding when waiting for overflow spinlock */
365     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
366 
367     /** The number of bits to use for reader count before overflowing */
368     private static final int LG_READERS = 7;
369 
370     // Values for lock state and stamp operations
371     private static final long RUNIT = 1L;
372     private static final long WBIT  = 1L << LG_READERS;
373     private static final long RBITS = WBIT - 1L;
374     private static final long RFULL = RBITS - 1L;
375     private static final long ABITS = RBITS | WBIT;
376     private static final long SBITS = ~RBITS; // note overlap with ABITS
377 
378     /*
379      * 3 stamp modes can be distinguished by examining (m = stamp & ABITS):
380      * write mode: m == WBIT
381      * optimistic read mode: m == 0L (even when read lock is held)
382      * read mode: m > 0L && m <= RFULL (the stamp is a copy of state, but the
383      * read hold count in the stamp is unused other than to determine mode)
384      *
385      * This differs slightly from the encoding of state:
386      * (state & ABITS) == 0L indicates the lock is currently unlocked.
387      * (state & ABITS) == RBITS is a special transient value
388      * indicating spin-locked to manipulate reader bits overflow.
389      */
390 
391     /** Initial value for lock state; avoids failure value zero. */
392     private static final long ORIGIN = WBIT << 1;
393 
394     // Special value from cancelled acquire methods so caller can throw IE
395     private static final long INTERRUPTED = 1L;
396 
397     // Values for node status; order matters
398     private static final int WAITING   = -1;
399     private static final int CANCELLED =  1;
400 
401     // Modes for nodes (int not boolean to allow arithmetic)
402     private static final int RMODE = 0;
403     private static final int WMODE = 1;
404 
405     /** Wait nodes */
406     static final class WNode {
407         volatile WNode prev;
408         volatile WNode next;
409         volatile WNode cowait;    // list of linked readers
410         volatile Thread thread;   // non-null while possibly parked
411         volatile int status;      // 0, WAITING, or CANCELLED
412         final int mode;           // RMODE or WMODE
WNode(int m, WNode p)413         WNode(int m, WNode p) { mode = m; prev = p; }
414     }
415 
416     /** Head of CLH queue */
417     private transient volatile WNode whead;
418     /** Tail (last) of CLH queue */
419     private transient volatile WNode wtail;
420 
421     // views
422     transient ReadLockView readLockView;
423     transient WriteLockView writeLockView;
424     transient ReadWriteLockView readWriteLockView;
425 
426     /** Lock sequence/state */
427     private transient volatile long state;
428     /** extra reader count when state read count saturated */
429     private transient int readerOverflow;
430 
431     /**
432      * Creates a new lock, initially in unlocked state.
433      */
StampedLock()434     public StampedLock() {
435         state = ORIGIN;
436     }
437 
casState(long expectedValue, long newValue)438     private boolean casState(long expectedValue, long newValue) {
439         return STATE.compareAndSet(this, expectedValue, newValue);
440     }
441 
tryWriteLock(long s)442     private long tryWriteLock(long s) {
443         // assert (s & ABITS) == 0L;
444         long next;
445         if (casState(s, next = s | WBIT)) {
446             VarHandle.storeStoreFence();
447             return next;
448         }
449         return 0L;
450     }
451 
452     /**
453      * Exclusively acquires the lock, blocking if necessary
454      * until available.
455      *
456      * @return a write stamp that can be used to unlock or convert mode
457      */
458     @ReservedStackAccess
writeLock()459     public long writeLock() {
460         long next;
461         return ((next = tryWriteLock()) != 0L) ? next : acquireWrite(false, 0L);
462     }
463 
464     /**
465      * Exclusively acquires the lock if it is immediately available.
466      *
467      * @return a write stamp that can be used to unlock or convert mode,
468      * or zero if the lock is not available
469      */
470     @ReservedStackAccess
tryWriteLock()471     public long tryWriteLock() {
472         long s;
473         return (((s = state) & ABITS) == 0L) ? tryWriteLock(s) : 0L;
474     }
475 
476     /**
477      * Exclusively acquires the lock if it is available within the
478      * given time and the current thread has not been interrupted.
479      * Behavior under timeout and interruption matches that specified
480      * for method {@link Lock#tryLock(long,TimeUnit)}.
481      *
482      * @param time the maximum time to wait for the lock
483      * @param unit the time unit of the {@code time} argument
484      * @return a write stamp that can be used to unlock or convert mode,
485      * or zero if the lock is not available
486      * @throws InterruptedException if the current thread is interrupted
487      * before acquiring the lock
488      */
tryWriteLock(long time, TimeUnit unit)489     public long tryWriteLock(long time, TimeUnit unit)
490         throws InterruptedException {
491         long nanos = unit.toNanos(time);
492         if (!Thread.interrupted()) {
493             long next, deadline;
494             if ((next = tryWriteLock()) != 0L)
495                 return next;
496             if (nanos <= 0L)
497                 return 0L;
498             if ((deadline = System.nanoTime() + nanos) == 0L)
499                 deadline = 1L;
500             if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
501                 return next;
502         }
503         throw new InterruptedException();
504     }
505 
506     /**
507      * Exclusively acquires the lock, blocking if necessary
508      * until available or the current thread is interrupted.
509      * Behavior under interruption matches that specified
510      * for method {@link Lock#lockInterruptibly()}.
511      *
512      * @return a write stamp that can be used to unlock or convert mode
513      * @throws InterruptedException if the current thread is interrupted
514      * before acquiring the lock
515      */
516     @ReservedStackAccess
writeLockInterruptibly()517     public long writeLockInterruptibly() throws InterruptedException {
518         long next;
519         if (!Thread.interrupted() &&
520             (next = acquireWrite(true, 0L)) != INTERRUPTED)
521             return next;
522         throw new InterruptedException();
523     }
524 
525     /**
526      * Non-exclusively acquires the lock, blocking if necessary
527      * until available.
528      *
529      * @return a read stamp that can be used to unlock or convert mode
530      */
531     @ReservedStackAccess
readLock()532     public long readLock() {
533         long s, next;
534         // bypass acquireRead on common uncontended case
535         return (whead == wtail
536                 && ((s = state) & ABITS) < RFULL
537                 && casState(s, next = s + RUNIT))
538             ? next
539             : acquireRead(false, 0L);
540     }
541 
542     /**
543      * Non-exclusively acquires the lock if it is immediately available.
544      *
545      * @return a read stamp that can be used to unlock or convert mode,
546      * or zero if the lock is not available
547      */
548     @ReservedStackAccess
tryReadLock()549     public long tryReadLock() {
550         long s, m, next;
551         while ((m = (s = state) & ABITS) != WBIT) {
552             if (m < RFULL) {
553                 if (casState(s, next = s + RUNIT))
554                     return next;
555             }
556             else if ((next = tryIncReaderOverflow(s)) != 0L)
557                 return next;
558         }
559         return 0L;
560     }
561 
562     /**
563      * Non-exclusively acquires the lock if it is available within the
564      * given time and the current thread has not been interrupted.
565      * Behavior under timeout and interruption matches that specified
566      * for method {@link Lock#tryLock(long,TimeUnit)}.
567      *
568      * @param time the maximum time to wait for the lock
569      * @param unit the time unit of the {@code time} argument
570      * @return a read stamp that can be used to unlock or convert mode,
571      * or zero if the lock is not available
572      * @throws InterruptedException if the current thread is interrupted
573      * before acquiring the lock
574      */
575     @ReservedStackAccess
tryReadLock(long time, TimeUnit unit)576     public long tryReadLock(long time, TimeUnit unit)
577         throws InterruptedException {
578         long s, m, next, deadline;
579         long nanos = unit.toNanos(time);
580         if (!Thread.interrupted()) {
581             if ((m = (s = state) & ABITS) != WBIT) {
582                 if (m < RFULL) {
583                     if (casState(s, next = s + RUNIT))
584                         return next;
585                 }
586                 else if ((next = tryIncReaderOverflow(s)) != 0L)
587                     return next;
588             }
589             if (nanos <= 0L)
590                 return 0L;
591             if ((deadline = System.nanoTime() + nanos) == 0L)
592                 deadline = 1L;
593             if ((next = acquireRead(true, deadline)) != INTERRUPTED)
594                 return next;
595         }
596         throw new InterruptedException();
597     }
598 
599     /**
600      * Non-exclusively acquires the lock, blocking if necessary
601      * until available or the current thread is interrupted.
602      * Behavior under interruption matches that specified
603      * for method {@link Lock#lockInterruptibly()}.
604      *
605      * @return a read stamp that can be used to unlock or convert mode
606      * @throws InterruptedException if the current thread is interrupted
607      * before acquiring the lock
608      */
609     @ReservedStackAccess
readLockInterruptibly()610     public long readLockInterruptibly() throws InterruptedException {
611         long s, next;
612         if (!Thread.interrupted()
613             // bypass acquireRead on common uncontended case
614             && ((whead == wtail
615                  && ((s = state) & ABITS) < RFULL
616                  && casState(s, next = s + RUNIT))
617                 ||
618                 (next = acquireRead(true, 0L)) != INTERRUPTED))
619             return next;
620         throw new InterruptedException();
621     }
622 
623     /**
624      * Returns a stamp that can later be validated, or zero
625      * if exclusively locked.
626      *
627      * @return a valid optimistic read stamp, or zero if exclusively locked
628      */
tryOptimisticRead()629     public long tryOptimisticRead() {
630         long s;
631         return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
632     }
633 
634     /**
635      * Returns true if the lock has not been exclusively acquired
636      * since issuance of the given stamp. Always returns false if the
637      * stamp is zero. Always returns true if the stamp represents a
638      * currently held lock. Invoking this method with a value not
639      * obtained from {@link #tryOptimisticRead} or a locking method
640      * for this lock has no defined effect or result.
641      *
642      * @param stamp a stamp
643      * @return {@code true} if the lock has not been exclusively acquired
644      * since issuance of the given stamp; else false
645      */
validate(long stamp)646     public boolean validate(long stamp) {
647         VarHandle.acquireFence();
648         return (stamp & SBITS) == (state & SBITS);
649     }
650 
651     /**
652      * Returns an unlocked state, incrementing the version and
653      * avoiding special failure value 0L.
654      *
655      * @param s a write-locked state (or stamp)
656      */
unlockWriteState(long s)657     private static long unlockWriteState(long s) {
658         return ((s += WBIT) == 0L) ? ORIGIN : s;
659     }
660 
unlockWriteInternal(long s)661     private long unlockWriteInternal(long s) {
662         long next; WNode h;
663         STATE.setVolatile(this, next = unlockWriteState(s));
664         if ((h = whead) != null && h.status != 0)
665             release(h);
666         return next;
667     }
668 
669     /**
670      * If the lock state matches the given stamp, releases the
671      * exclusive lock.
672      *
673      * @param stamp a stamp returned by a write-lock operation
674      * @throws IllegalMonitorStateException if the stamp does
675      * not match the current state of this lock
676      */
677     @ReservedStackAccess
unlockWrite(long stamp)678     public void unlockWrite(long stamp) {
679         if (state != stamp || (stamp & WBIT) == 0L)
680             throw new IllegalMonitorStateException();
681         unlockWriteInternal(stamp);
682     }
683 
684     /**
685      * If the lock state matches the given stamp, releases the
686      * non-exclusive lock.
687      *
688      * @param stamp a stamp returned by a read-lock operation
689      * @throws IllegalMonitorStateException if the stamp does
690      * not match the current state of this lock
691      */
692     @ReservedStackAccess
unlockRead(long stamp)693     public void unlockRead(long stamp) {
694         long s, m; WNode h;
695         while (((s = state) & SBITS) == (stamp & SBITS)
696                && (stamp & RBITS) > 0L
697                && ((m = s & RBITS) > 0L)) {
698             if (m < RFULL) {
699                 if (casState(s, s - RUNIT)) {
700                     if (m == RUNIT && (h = whead) != null && h.status != 0)
701                         release(h);
702                     return;
703                 }
704             }
705             else if (tryDecReaderOverflow(s) != 0L)
706                 return;
707         }
708         throw new IllegalMonitorStateException();
709     }
710 
711     /**
712      * If the lock state matches the given stamp, releases the
713      * corresponding mode of the lock.
714      *
715      * @param stamp a stamp returned by a lock operation
716      * @throws IllegalMonitorStateException if the stamp does
717      * not match the current state of this lock
718      */
719     @ReservedStackAccess
unlock(long stamp)720     public void unlock(long stamp) {
721         if ((stamp & WBIT) != 0L)
722             unlockWrite(stamp);
723         else
724             unlockRead(stamp);
725     }
726 
727     /**
728      * If the lock state matches the given stamp, atomically performs one of
729      * the following actions. If the stamp represents holding a write
730      * lock, returns it.  Or, if a read lock, if the write lock is
731      * available, releases the read lock and returns a write stamp.
732      * Or, if an optimistic read, returns a write stamp only if
733      * immediately available. This method returns zero in all other
734      * cases.
735      *
736      * @param stamp a stamp
737      * @return a valid write stamp, or zero on failure
738      */
tryConvertToWriteLock(long stamp)739     public long tryConvertToWriteLock(long stamp) {
740         long a = stamp & ABITS, m, s, next;
741         while (((s = state) & SBITS) == (stamp & SBITS)) {
742             if ((m = s & ABITS) == 0L) {
743                 if (a != 0L)
744                     break;
745                 if ((next = tryWriteLock(s)) != 0L)
746                     return next;
747             }
748             else if (m == WBIT) {
749                 if (a != m)
750                     break;
751                 return stamp;
752             }
753             else if (m == RUNIT && a != 0L) {
754                 if (casState(s, next = s - RUNIT + WBIT)) {
755                     VarHandle.storeStoreFence();
756                     return next;
757                 }
758             }
759             else
760                 break;
761         }
762         return 0L;
763     }
764 
765     /**
766      * If the lock state matches the given stamp, atomically performs one of
767      * the following actions. If the stamp represents holding a write
768      * lock, releases it and obtains a read lock.  Or, if a read lock,
769      * returns it. Or, if an optimistic read, acquires a read lock and
770      * returns a read stamp only if immediately available. This method
771      * returns zero in all other cases.
772      *
773      * @param stamp a stamp
774      * @return a valid read stamp, or zero on failure
775      */
tryConvertToReadLock(long stamp)776     public long tryConvertToReadLock(long stamp) {
777         long a, s, next; WNode h;
778         while (((s = state) & SBITS) == (stamp & SBITS)) {
779             if ((a = stamp & ABITS) >= WBIT) {
780                 // write stamp
781                 if (s != stamp)
782                     break;
783                 STATE.setVolatile(this, next = unlockWriteState(s) + RUNIT);
784                 if ((h = whead) != null && h.status != 0)
785                     release(h);
786                 return next;
787             }
788             else if (a == 0L) {
789                 // optimistic read stamp
790                 if ((s & ABITS) < RFULL) {
791                     if (casState(s, next = s + RUNIT))
792                         return next;
793                 }
794                 else if ((next = tryIncReaderOverflow(s)) != 0L)
795                     return next;
796             }
797             else {
798                 // already a read stamp
799                 if ((s & ABITS) == 0L)
800                     break;
801                 return stamp;
802             }
803         }
804         return 0L;
805     }
806 
807     /**
808      * If the lock state matches the given stamp then, atomically, if the stamp
809      * represents holding a lock, releases it and returns an
810      * observation stamp.  Or, if an optimistic read, returns it if
811      * validated. This method returns zero in all other cases, and so
812      * may be useful as a form of "tryUnlock".
813      *
814      * @param stamp a stamp
815      * @return a valid optimistic read stamp, or zero on failure
816      */
tryConvertToOptimisticRead(long stamp)817     public long tryConvertToOptimisticRead(long stamp) {
818         long a, m, s, next; WNode h;
819         VarHandle.acquireFence();
820         while (((s = state) & SBITS) == (stamp & SBITS)) {
821             if ((a = stamp & ABITS) >= WBIT) {
822                 // write stamp
823                 if (s != stamp)
824                     break;
825                 return unlockWriteInternal(s);
826             }
827             else if (a == 0L)
828                 // already an optimistic read stamp
829                 return stamp;
830             else if ((m = s & ABITS) == 0L) // invalid read stamp
831                 break;
832             else if (m < RFULL) {
833                 if (casState(s, next = s - RUNIT)) {
834                     if (m == RUNIT && (h = whead) != null && h.status != 0)
835                         release(h);
836                     return next & SBITS;
837                 }
838             }
839             else if ((next = tryDecReaderOverflow(s)) != 0L)
840                 return next & SBITS;
841         }
842         return 0L;
843     }
844 
845     /**
846      * Releases the write lock if it is held, without requiring a
847      * stamp value. This method may be useful for recovery after
848      * errors.
849      *
850      * @return {@code true} if the lock was held, else false
851      */
852     @ReservedStackAccess
tryUnlockWrite()853     public boolean tryUnlockWrite() {
854         long s;
855         if (((s = state) & WBIT) != 0L) {
856             unlockWriteInternal(s);
857             return true;
858         }
859         return false;
860     }
861 
862     /**
863      * Releases one hold of the read lock if it is held, without
864      * requiring a stamp value. This method may be useful for recovery
865      * after errors.
866      *
867      * @return {@code true} if the read lock was held, else false
868      */
869     @ReservedStackAccess
tryUnlockRead()870     public boolean tryUnlockRead() {
871         long s, m; WNode h;
872         while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
873             if (m < RFULL) {
874                 if (casState(s, s - RUNIT)) {
875                     if (m == RUNIT && (h = whead) != null && h.status != 0)
876                         release(h);
877                     return true;
878                 }
879             }
880             else if (tryDecReaderOverflow(s) != 0L)
881                 return true;
882         }
883         return false;
884     }
885 
886     // status monitoring methods
887 
888     /**
889      * Returns combined state-held and overflow read count for given
890      * state s.
891      */
getReadLockCount(long s)892     private int getReadLockCount(long s) {
893         long readers;
894         if ((readers = s & RBITS) >= RFULL)
895             readers = RFULL + readerOverflow;
896         return (int) readers;
897     }
898 
899     /**
900      * Returns {@code true} if the lock is currently held exclusively.
901      *
902      * @return {@code true} if the lock is currently held exclusively
903      */
isWriteLocked()904     public boolean isWriteLocked() {
905         return (state & WBIT) != 0L;
906     }
907 
908     /**
909      * Returns {@code true} if the lock is currently held non-exclusively.
910      *
911      * @return {@code true} if the lock is currently held non-exclusively
912      */
isReadLocked()913     public boolean isReadLocked() {
914         return (state & RBITS) != 0L;
915     }
916 
917     /**
918      * Tells whether a stamp represents holding a lock exclusively.
919      * This method may be useful in conjunction with
920      * {@link #tryConvertToWriteLock}, for example: <pre> {@code
921      * long stamp = sl.tryOptimisticRead();
922      * try {
923      *   ...
924      *   stamp = sl.tryConvertToWriteLock(stamp);
925      *   ...
926      * } finally {
927      *   if (StampedLock.isWriteLockStamp(stamp))
928      *     sl.unlockWrite(stamp);
929      * }}</pre>
930      *
931      * @param stamp a stamp returned by a previous StampedLock operation
932      * @return {@code true} if the stamp was returned by a successful
933      *   write-lock operation
934      * @since 10
935      */
isWriteLockStamp(long stamp)936     public static boolean isWriteLockStamp(long stamp) {
937         return (stamp & ABITS) == WBIT;
938     }
939 
940     /**
941      * Tells whether a stamp represents holding a lock non-exclusively.
942      * This method may be useful in conjunction with
943      * {@link #tryConvertToReadLock}, for example: <pre> {@code
944      * long stamp = sl.tryOptimisticRead();
945      * try {
946      *   ...
947      *   stamp = sl.tryConvertToReadLock(stamp);
948      *   ...
949      * } finally {
950      *   if (StampedLock.isReadLockStamp(stamp))
951      *     sl.unlockRead(stamp);
952      * }}</pre>
953      *
954      * @param stamp a stamp returned by a previous StampedLock operation
955      * @return {@code true} if the stamp was returned by a successful
956      *   read-lock operation
957      * @since 10
958      */
isReadLockStamp(long stamp)959     public static boolean isReadLockStamp(long stamp) {
960         return (stamp & RBITS) != 0L;
961     }
962 
963     /**
964      * Tells whether a stamp represents holding a lock.
965      * This method may be useful in conjunction with
966      * {@link #tryConvertToReadLock} and {@link #tryConvertToWriteLock},
967      * for example: <pre> {@code
968      * long stamp = sl.tryOptimisticRead();
969      * try {
970      *   ...
971      *   stamp = sl.tryConvertToReadLock(stamp);
972      *   ...
973      *   stamp = sl.tryConvertToWriteLock(stamp);
974      *   ...
975      * } finally {
976      *   if (StampedLock.isLockStamp(stamp))
977      *     sl.unlock(stamp);
978      * }}</pre>
979      *
980      * @param stamp a stamp returned by a previous StampedLock operation
981      * @return {@code true} if the stamp was returned by a successful
982      *   read-lock or write-lock operation
983      * @since 10
984      */
isLockStamp(long stamp)985     public static boolean isLockStamp(long stamp) {
986         return (stamp & ABITS) != 0L;
987     }
988 
989     /**
990      * Tells whether a stamp represents a successful optimistic read.
991      *
992      * @param stamp a stamp returned by a previous StampedLock operation
993      * @return {@code true} if the stamp was returned by a successful
994      *   optimistic read operation, that is, a non-zero return from
995      *   {@link #tryOptimisticRead()} or
996      *   {@link #tryConvertToOptimisticRead(long)}
997      * @since 10
998      */
isOptimisticReadStamp(long stamp)999     public static boolean isOptimisticReadStamp(long stamp) {
1000         return (stamp & ABITS) == 0L && stamp != 0L;
1001     }
1002 
1003     /**
1004      * Queries the number of read locks held for this lock. This
1005      * method is designed for use in monitoring system state, not for
1006      * synchronization control.
1007      * @return the number of read locks held
1008      */
getReadLockCount()1009     public int getReadLockCount() {
1010         return getReadLockCount(state);
1011     }
1012 
1013     /**
1014      * Returns a string identifying this lock, as well as its lock
1015      * state.  The state, in brackets, includes the String {@code
1016      * "Unlocked"} or the String {@code "Write-locked"} or the String
1017      * {@code "Read-locks:"} followed by the current number of
1018      * read-locks held.
1019      *
1020      * @return a string identifying this lock, as well as its lock state
1021      */
toString()1022     public String toString() {
1023         long s = state;
1024         return super.toString() +
1025             ((s & ABITS) == 0L ? "[Unlocked]" :
1026              (s & WBIT) != 0L ? "[Write-locked]" :
1027              "[Read-locks:" + getReadLockCount(s) + "]");
1028     }
1029 
1030     // views
1031 
1032     /**
1033      * Returns a plain {@link Lock} view of this StampedLock in which
1034      * the {@link Lock#lock} method is mapped to {@link #readLock},
1035      * and similarly for other methods. The returned Lock does not
1036      * support a {@link Condition}; method {@link Lock#newCondition()}
1037      * throws {@code UnsupportedOperationException}.
1038      *
1039      * @return the lock
1040      */
asReadLock()1041     public Lock asReadLock() {
1042         ReadLockView v;
1043         if ((v = readLockView) != null) return v;
1044         return readLockView = new ReadLockView();
1045     }
1046 
1047     /**
1048      * Returns a plain {@link Lock} view of this StampedLock in which
1049      * the {@link Lock#lock} method is mapped to {@link #writeLock},
1050      * and similarly for other methods. The returned Lock does not
1051      * support a {@link Condition}; method {@link Lock#newCondition()}
1052      * throws {@code UnsupportedOperationException}.
1053      *
1054      * @return the lock
1055      */
asWriteLock()1056     public Lock asWriteLock() {
1057         WriteLockView v;
1058         if ((v = writeLockView) != null) return v;
1059         return writeLockView = new WriteLockView();
1060     }
1061 
1062     /**
1063      * Returns a {@link ReadWriteLock} view of this StampedLock in
1064      * which the {@link ReadWriteLock#readLock()} method is mapped to
1065      * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to
1066      * {@link #asWriteLock()}.
1067      *
1068      * @return the lock
1069      */
asReadWriteLock()1070     public ReadWriteLock asReadWriteLock() {
1071         ReadWriteLockView v;
1072         if ((v = readWriteLockView) != null) return v;
1073         return readWriteLockView = new ReadWriteLockView();
1074     }
1075 
1076     // view classes
1077 
1078     final class ReadLockView implements Lock {
lock()1079         public void lock() { readLock(); }
lockInterruptibly()1080         public void lockInterruptibly() throws InterruptedException {
1081             readLockInterruptibly();
1082         }
tryLock()1083         public boolean tryLock() { return tryReadLock() != 0L; }
tryLock(long time, TimeUnit unit)1084         public boolean tryLock(long time, TimeUnit unit)
1085             throws InterruptedException {
1086             return tryReadLock(time, unit) != 0L;
1087         }
unlock()1088         public void unlock() { unstampedUnlockRead(); }
newCondition()1089         public Condition newCondition() {
1090             throw new UnsupportedOperationException();
1091         }
1092     }
1093 
1094     final class WriteLockView implements Lock {
lock()1095         public void lock() { writeLock(); }
lockInterruptibly()1096         public void lockInterruptibly() throws InterruptedException {
1097             writeLockInterruptibly();
1098         }
tryLock()1099         public boolean tryLock() { return tryWriteLock() != 0L; }
tryLock(long time, TimeUnit unit)1100         public boolean tryLock(long time, TimeUnit unit)
1101             throws InterruptedException {
1102             return tryWriteLock(time, unit) != 0L;
1103         }
unlock()1104         public void unlock() { unstampedUnlockWrite(); }
newCondition()1105         public Condition newCondition() {
1106             throw new UnsupportedOperationException();
1107         }
1108     }
1109 
1110     final class ReadWriteLockView implements ReadWriteLock {
readLock()1111         public Lock readLock() { return asReadLock(); }
writeLock()1112         public Lock writeLock() { return asWriteLock(); }
1113     }
1114 
1115     // Unlock methods without stamp argument checks for view classes.
1116     // Needed because view-class lock methods throw away stamps.
1117 
unstampedUnlockWrite()1118     final void unstampedUnlockWrite() {
1119         long s;
1120         if (((s = state) & WBIT) == 0L)
1121             throw new IllegalMonitorStateException();
1122         unlockWriteInternal(s);
1123     }
1124 
unstampedUnlockRead()1125     final void unstampedUnlockRead() {
1126         long s, m; WNode h;
1127         while ((m = (s = state) & RBITS) > 0L) {
1128             if (m < RFULL) {
1129                 if (casState(s, s - RUNIT)) {
1130                     if (m == RUNIT && (h = whead) != null && h.status != 0)
1131                         release(h);
1132                     return;
1133                 }
1134             }
1135             else if (tryDecReaderOverflow(s) != 0L)
1136                 return;
1137         }
1138         throw new IllegalMonitorStateException();
1139     }
1140 
readObject(java.io.ObjectInputStream s)1141     private void readObject(java.io.ObjectInputStream s)
1142         throws java.io.IOException, ClassNotFoundException {
1143         s.defaultReadObject();
1144         STATE.setVolatile(this, ORIGIN); // reset to unlocked state
1145     }
1146 
1147     // internals
1148 
1149     /**
1150      * Tries to increment readerOverflow by first setting state
1151      * access bits value to RBITS, indicating hold of spinlock,
1152      * then updating, then releasing.
1153      *
1154      * @param s a reader overflow stamp: (s & ABITS) >= RFULL
1155      * @return new stamp on success, else zero
1156      */
tryIncReaderOverflow(long s)1157     private long tryIncReaderOverflow(long s) {
1158         // assert (s & ABITS) >= RFULL;
1159         if ((s & ABITS) == RFULL) {
1160             if (casState(s, s | RBITS)) {
1161                 ++readerOverflow;
1162                 STATE.setVolatile(this, s);
1163                 return s;
1164             }
1165         }
1166         else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
1167             Thread.yield();
1168         // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1169         // else
1170         //     Thread.onSpinWait();
1171         return 0L;
1172     }
1173 
1174     /**
1175      * Tries to decrement readerOverflow.
1176      *
1177      * @param s a reader overflow stamp: (s & ABITS) >= RFULL
1178      * @return new stamp on success, else zero
1179      */
tryDecReaderOverflow(long s)1180     private long tryDecReaderOverflow(long s) {
1181         // assert (s & ABITS) >= RFULL;
1182         if ((s & ABITS) == RFULL) {
1183             if (casState(s, s | RBITS)) {
1184                 int r; long next;
1185                 if ((r = readerOverflow) > 0) {
1186                     readerOverflow = r - 1;
1187                     next = s;
1188                 }
1189                 else
1190                     next = s - RUNIT;
1191                 STATE.setVolatile(this, next);
1192                 return next;
1193             }
1194         }
1195         else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
1196             Thread.yield();
1197         // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1198         // else
1199         //     Thread.onSpinWait();
1200         return 0L;
1201     }
1202 
1203     /**
1204      * Wakes up the successor of h (normally whead). This is normally
1205      * just h.next, but may require traversal from wtail if next
1206      * pointers are lagging. This may fail to wake up an acquiring
1207      * thread when one or more have been cancelled, but the cancel
1208      * methods themselves provide extra safeguards to ensure liveness.
1209      */
release(WNode h)1210     private void release(WNode h) {
1211         if (h != null) {
1212             WNode q; Thread w;
1213             WSTATUS.compareAndSet(h, WAITING, 0);
1214             if ((q = h.next) == null || q.status == CANCELLED) {
1215                 for (WNode t = wtail; t != null && t != h; t = t.prev)
1216                     if (t.status <= 0)
1217                         q = t;
1218             }
1219             if (q != null && (w = q.thread) != null)
1220                 LockSupport.unpark(w);
1221         }
1222     }
1223 
1224     /**
1225      * See above for explanation.
1226      *
1227      * @param interruptible true if should check interrupts and if so
1228      * return INTERRUPTED
1229      * @param deadline if nonzero, the System.nanoTime value to timeout
1230      * at (and return zero)
1231      * @return next state, or INTERRUPTED
1232      */
acquireWrite(boolean interruptible, long deadline)1233     private long acquireWrite(boolean interruptible, long deadline) {
1234         WNode node = null, p;
1235         for (int spins = -1;;) { // spin while enqueuing
1236             long m, s, ns;
1237             if ((m = (s = state) & ABITS) == 0L) {
1238                 if ((ns = tryWriteLock(s)) != 0L)
1239                     return ns;
1240             }
1241             else if (spins < 0)
1242                 spins = (m == WBIT && wtail == whead) ? SPINS : 0;
1243             else if (spins > 0) {
1244                 --spins;
1245                 // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1246                 // Thread.onSpinWait();
1247             }
1248             else if ((p = wtail) == null) { // initialize queue
1249                 WNode hd = new WNode(WMODE, null);
1250                 if (WHEAD.weakCompareAndSet(this, null, hd))
1251                     wtail = hd;
1252             }
1253             else if (node == null)
1254                 node = new WNode(WMODE, p);
1255             else if (node.prev != p)
1256                 node.prev = p;
1257             else if (WTAIL.weakCompareAndSet(this, p, node)) {
1258                 p.next = node;
1259                 break;
1260             }
1261         }
1262 
1263         boolean wasInterrupted = false;
1264         for (int spins = -1;;) {
1265             WNode h, np, pp; int ps;
1266             if ((h = whead) == p) {
1267                 if (spins < 0)
1268                     spins = HEAD_SPINS;
1269                 else if (spins < MAX_HEAD_SPINS)
1270                     spins <<= 1;
1271                 for (int k = spins; k > 0; --k) { // spin at head
1272                     long s, ns;
1273                     if (((s = state) & ABITS) == 0L) {
1274                         if ((ns = tryWriteLock(s)) != 0L) {
1275                             whead = node;
1276                             node.prev = null;
1277                             if (wasInterrupted)
1278                                 Thread.currentThread().interrupt();
1279                             return ns;
1280                         }
1281                     }
1282                     // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1283                     // else
1284                     //     Thread.onSpinWait();
1285                 }
1286             }
1287             else if (h != null) { // help release stale waiters
1288                 WNode c; Thread w;
1289                 while ((c = h.cowait) != null) {
1290                     if (WCOWAIT.weakCompareAndSet(h, c, c.cowait) &&
1291                         (w = c.thread) != null)
1292                         LockSupport.unpark(w);
1293                 }
1294             }
1295             if (whead == h) {
1296                 if ((np = node.prev) != p) {
1297                     if (np != null)
1298                         (p = np).next = node;   // stale
1299                 }
1300                 else if ((ps = p.status) == 0)
1301                     WSTATUS.compareAndSet(p, 0, WAITING);
1302                 else if (ps == CANCELLED) {
1303                     if ((pp = p.prev) != null) {
1304                         node.prev = pp;
1305                         pp.next = node;
1306                     }
1307                 }
1308                 else {
1309                     long time; // 0 argument to park means no timeout
1310                     if (deadline == 0L)
1311                         time = 0L;
1312                     else if ((time = deadline - System.nanoTime()) <= 0L)
1313                         return cancelWaiter(node, node, false);
1314                     Thread wt = Thread.currentThread();
1315                     node.thread = wt;
1316                     if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
1317                         whead == h && node.prev == p) {
1318                         if (time == 0L)
1319                             LockSupport.park(this);
1320                         else
1321                             LockSupport.parkNanos(this, time);
1322                     }
1323                     node.thread = null;
1324                     if (Thread.interrupted()) {
1325                         if (interruptible)
1326                             return cancelWaiter(node, node, true);
1327                         wasInterrupted = true;
1328                     }
1329                 }
1330             }
1331         }
1332     }
1333 
1334     /**
1335      * See above for explanation.
1336      *
1337      * @param interruptible true if should check interrupts and if so
1338      * return INTERRUPTED
1339      * @param deadline if nonzero, the System.nanoTime value to timeout
1340      * at (and return zero)
1341      * @return next state, or INTERRUPTED
1342      */
acquireRead(boolean interruptible, long deadline)1343     private long acquireRead(boolean interruptible, long deadline) {
1344         boolean wasInterrupted = false;
1345         WNode node = null, p;
1346         for (int spins = -1;;) {
1347             WNode h;
1348             if ((h = whead) == (p = wtail)) {
1349                 for (long m, s, ns;;) {
1350                     if ((m = (s = state) & ABITS) < RFULL ?
1351                         casState(s, ns = s + RUNIT) :
1352                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
1353                         if (wasInterrupted)
1354                             Thread.currentThread().interrupt();
1355                         return ns;
1356                     }
1357                     else if (m >= WBIT) {
1358                         if (spins > 0) {
1359                             --spins;
1360                             // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1361                             // Thread.onSpinWait();
1362                         }
1363                         else {
1364                             if (spins == 0) {
1365                                 WNode nh = whead, np = wtail;
1366                                 if ((nh == h && np == p) || (h = nh) != (p = np))
1367                                     break;
1368                             }
1369                             spins = SPINS;
1370                         }
1371                     }
1372                 }
1373             }
1374             if (p == null) { // initialize queue
1375                 WNode hd = new WNode(WMODE, null);
1376                 if (WHEAD.weakCompareAndSet(this, null, hd))
1377                     wtail = hd;
1378             }
1379             else if (node == null)
1380                 node = new WNode(RMODE, p);
1381             else if (h == p || p.mode != RMODE) {
1382                 if (node.prev != p)
1383                     node.prev = p;
1384                 else if (WTAIL.weakCompareAndSet(this, p, node)) {
1385                     p.next = node;
1386                     break;
1387                 }
1388             }
1389             else if (!WCOWAIT.compareAndSet(p, node.cowait = p.cowait, node))
1390                 node.cowait = null;
1391             else {
1392                 for (;;) {
1393                     WNode pp, c; Thread w;
1394                     if ((h = whead) != null && (c = h.cowait) != null &&
1395                         WCOWAIT.compareAndSet(h, c, c.cowait) &&
1396                         (w = c.thread) != null) // help release
1397                         LockSupport.unpark(w);
1398                     if (Thread.interrupted()) {
1399                         if (interruptible)
1400                             return cancelWaiter(node, p, true);
1401                         wasInterrupted = true;
1402                     }
1403                     if (h == (pp = p.prev) || h == p || pp == null) {
1404                         long m, s, ns;
1405                         do {
1406                             if ((m = (s = state) & ABITS) < RFULL ?
1407                                 casState(s, ns = s + RUNIT) :
1408                                 (m < WBIT &&
1409                                  (ns = tryIncReaderOverflow(s)) != 0L)) {
1410                                 if (wasInterrupted)
1411                                     Thread.currentThread().interrupt();
1412                                 return ns;
1413                             }
1414                         } while (m < WBIT);
1415                     }
1416                     if (whead == h && p.prev == pp) {
1417                         long time;
1418                         if (pp == null || h == p || p.status > 0) {
1419                             node = null; // throw away
1420                             break;
1421                         }
1422                         if (deadline == 0L)
1423                             time = 0L;
1424                         else if ((time = deadline - System.nanoTime()) <= 0L) {
1425                             if (wasInterrupted)
1426                                 Thread.currentThread().interrupt();
1427                             return cancelWaiter(node, p, false);
1428                         }
1429                         Thread wt = Thread.currentThread();
1430                         node.thread = wt;
1431                         if ((h != pp || (state & ABITS) == WBIT) &&
1432                             whead == h && p.prev == pp) {
1433                             if (time == 0L)
1434                                 LockSupport.park(this);
1435                             else
1436                                 LockSupport.parkNanos(this, time);
1437                         }
1438                         node.thread = null;
1439                     }
1440                 }
1441             }
1442         }
1443 
1444         for (int spins = -1;;) {
1445             WNode h, np, pp; int ps;
1446             if ((h = whead) == p) {
1447                 if (spins < 0)
1448                     spins = HEAD_SPINS;
1449                 else if (spins < MAX_HEAD_SPINS)
1450                     spins <<= 1;
1451                 for (int k = spins;;) { // spin at head
1452                     long m, s, ns;
1453                     if ((m = (s = state) & ABITS) < RFULL ?
1454                         casState(s, ns = s + RUNIT) :
1455                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
1456                         WNode c; Thread w;
1457                         whead = node;
1458                         node.prev = null;
1459                         while ((c = node.cowait) != null) {
1460                             if (WCOWAIT.compareAndSet(node, c, c.cowait) &&
1461                                 (w = c.thread) != null)
1462                                 LockSupport.unpark(w);
1463                         }
1464                         if (wasInterrupted)
1465                             Thread.currentThread().interrupt();
1466                         return ns;
1467                     }
1468                     else if (m >= WBIT && --k <= 0)
1469                         break;
1470                     // Android-removed: remove usage of Thread.onSpinWait. http://b/202837191
1471                     // else
1472                     //     Thread.onSpinWait();
1473                 }
1474             }
1475             else if (h != null) {
1476                 WNode c; Thread w;
1477                 while ((c = h.cowait) != null) {
1478                     if (WCOWAIT.compareAndSet(h, c, c.cowait) &&
1479                         (w = c.thread) != null)
1480                         LockSupport.unpark(w);
1481                 }
1482             }
1483             if (whead == h) {
1484                 if ((np = node.prev) != p) {
1485                     if (np != null)
1486                         (p = np).next = node;   // stale
1487                 }
1488                 else if ((ps = p.status) == 0)
1489                     WSTATUS.compareAndSet(p, 0, WAITING);
1490                 else if (ps == CANCELLED) {
1491                     if ((pp = p.prev) != null) {
1492                         node.prev = pp;
1493                         pp.next = node;
1494                     }
1495                 }
1496                 else {
1497                     long time;
1498                     if (deadline == 0L)
1499                         time = 0L;
1500                     else if ((time = deadline - System.nanoTime()) <= 0L)
1501                         return cancelWaiter(node, node, false);
1502                     Thread wt = Thread.currentThread();
1503                     node.thread = wt;
1504                     if (p.status < 0 &&
1505                         (p != h || (state & ABITS) == WBIT) &&
1506                         whead == h && node.prev == p) {
1507                             if (time == 0L)
1508                                 LockSupport.park(this);
1509                             else
1510                                 LockSupport.parkNanos(this, time);
1511                     }
1512                     node.thread = null;
1513                     if (Thread.interrupted()) {
1514                         if (interruptible)
1515                             return cancelWaiter(node, node, true);
1516                         wasInterrupted = true;
1517                     }
1518                 }
1519             }
1520         }
1521     }
1522 
1523     /**
1524      * If node non-null, forces cancel status and unsplices it from
1525      * queue if possible and wakes up any cowaiters (of the node, or
1526      * group, as applicable), and in any case helps release current
1527      * first waiter if lock is free. (Calling with null arguments
1528      * serves as a conditional form of release, which is not currently
1529      * needed but may be needed under possible future cancellation
1530      * policies). This is a variant of cancellation methods in
1531      * AbstractQueuedSynchronizer (see its detailed explanation in AQS
1532      * internal documentation).
1533      *
1534      * @param node if non-null, the waiter
1535      * @param group either node or the group node is cowaiting with
1536      * @param interrupted if already interrupted
1537      * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
1538      */
cancelWaiter(WNode node, WNode group, boolean interrupted)1539     private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
1540         if (node != null && group != null) {
1541             Thread w;
1542             node.status = CANCELLED;
1543             // unsplice cancelled nodes from group
1544             for (WNode p = group, q; (q = p.cowait) != null;) {
1545                 if (q.status == CANCELLED) {
1546                     WCOWAIT.compareAndSet(p, q, q.cowait);
1547                     p = group; // restart
1548                 }
1549                 else
1550                     p = q;
1551             }
1552             if (group == node) {
1553                 for (WNode r = group.cowait; r != null; r = r.cowait) {
1554                     if ((w = r.thread) != null)
1555                         LockSupport.unpark(w); // wake up uncancelled co-waiters
1556                 }
1557                 for (WNode pred = node.prev; pred != null; ) { // unsplice
1558                     WNode succ, pp;        // find valid successor
1559                     while ((succ = node.next) == null ||
1560                            succ.status == CANCELLED) {
1561                         WNode q = null;    // find successor the slow way
1562                         for (WNode t = wtail; t != null && t != node; t = t.prev)
1563                             if (t.status != CANCELLED)
1564                                 q = t;     // don't link if succ cancelled
1565                         if (succ == q ||   // ensure accurate successor
1566                             WNEXT.compareAndSet(node, succ, succ = q)) {
1567                             if (succ == null && node == wtail)
1568                                 WTAIL.compareAndSet(this, node, pred);
1569                             break;
1570                         }
1571                     }
1572                     if (pred.next == node) // unsplice pred link
1573                         WNEXT.compareAndSet(pred, node, succ);
1574                     if (succ != null && (w = succ.thread) != null) {
1575                         // wake up succ to observe new pred
1576                         succ.thread = null;
1577                         LockSupport.unpark(w);
1578                     }
1579                     if (pred.status != CANCELLED || (pp = pred.prev) == null)
1580                         break;
1581                     node.prev = pp;        // repeat if new pred wrong/cancelled
1582                     WNEXT.compareAndSet(pp, pred, succ);
1583                     pred = pp;
1584                 }
1585             }
1586         }
1587         WNode h; // Possibly release first waiter
1588         while ((h = whead) != null) {
1589             long s; WNode q; // similar to release() but check eligibility
1590             if ((q = h.next) == null || q.status == CANCELLED) {
1591                 for (WNode t = wtail; t != null && t != h; t = t.prev)
1592                     if (t.status <= 0)
1593                         q = t;
1594             }
1595             if (h == whead) {
1596                 if (q != null && h.status == 0 &&
1597                     ((s = state) & ABITS) != WBIT && // waiter is eligible
1598                     (s == 0L || q.mode == RMODE))
1599                     release(h);
1600                 break;
1601             }
1602         }
1603         return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1604     }
1605 
1606     // VarHandle mechanics
1607     private static final VarHandle STATE;
1608     private static final VarHandle WHEAD;
1609     private static final VarHandle WTAIL;
1610     private static final VarHandle WNEXT;
1611     private static final VarHandle WSTATUS;
1612     private static final VarHandle WCOWAIT;
1613     static {
1614         try {
1615             MethodHandles.Lookup l = MethodHandles.lookup();
1616             STATE = l.findVarHandle(StampedLock.class, "state", long.class);
1617             WHEAD = l.findVarHandle(StampedLock.class, "whead", WNode.class);
1618             WTAIL = l.findVarHandle(StampedLock.class, "wtail", WNode.class);
1619             WSTATUS = l.findVarHandle(WNode.class, "status", int.class);
1620             WNEXT = l.findVarHandle(WNode.class, "next", WNode.class);
1621             WCOWAIT = l.findVarHandle(WNode.class, "cowait", WNode.class);
1622         } catch (ReflectiveOperationException e) {
1623             throw new ExceptionInInitializerError(e);
1624         }
1625     }
1626 }
1627