ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
(Generate patch)

Comparing jsr166/src/jsr166e/StampedLock.java (file contents):
Revision 1.2 by jsr166, Fri Oct 12 16:22:40 2012 UTC vs.
Revision 1.38 by dl, Mon Aug 19 14:30:37 2013 UTC

# Line 5 | Line 5
5   */
6  
7   package jsr166e;
8
9 import java.util.concurrent.ThreadLocalRandom;
8   import java.util.concurrent.TimeUnit;
9 + import java.util.concurrent.locks.Lock;
10 + import java.util.concurrent.locks.Condition;
11 + import java.util.concurrent.locks.ReadWriteLock;
12 + import java.util.concurrent.locks.LockSupport;
13  
14   /**
15   * A capability-based lock with three modes for controlling read/write
16 < * access.  The state of a StampedLock consists of a version and
17 < * mode. Lock acquisition methods return a stamp that represents and
16 > * access.  The state of a StampedLock consists of a version and mode.
17 > * Lock acquisition methods return a stamp that represents and
18   * controls access with respect to a lock state; "try" versions of
19   * these methods may instead return the special value zero to
20   * represent failure to acquire access. Lock release and conversion
# Line 26 | Line 28 | import java.util.concurrent.TimeUnit;
28   *   in method {@link #unlockWrite} to release the lock. Untimed and
29   *   timed versions of {@code tryWriteLock} are also provided. When
30   *   the lock is held in write mode, no read locks may be obtained,
31 < *   and all observer validations will fail.  </li>
31 > *   and all optimistic read validations will fail.  </li>
32   *
33   *  <li><b>Reading.</b> Method {@link #readLock} possibly blocks
34   *   waiting for non-exclusive access, returning a stamp that can be
# Line 36 | Line 38 | import java.util.concurrent.TimeUnit;
38   *  <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
39   *   returns a non-zero stamp only if the lock is not currently held
40   *   in write mode. Method {@link #validate} returns true if the lock
41 < *   has not since been acquired in write mode. This mode can be
42 < *   thought of as an extremely weak version of a read-lock, that can
43 < *   be broken by a writer at any time.  The use of optimistic mode
44 < *   for short read-only code segments often reduces contention and
45 < *   improves throughput.  However, its use is inherently fragile.
46 < *   Optimistic read sections should only read fields and hold them in
47 < *   local variables for later use after validation. Fields read while
48 < *   in optimistic mode may be wildly inconsistent, so usage applies
49 < *   only when you are familiar enough with data representations to
50 < *   check consistency and/or repeatedly invoke method {@code
51 < *   validate()}.  For example, such steps are typically required when
52 < *   first reading an object or array reference, and then accessing
53 < *   one of its fields, elements or methods. </li>
41 > *   has not been acquired in write mode since obtaining a given
42 > *   stamp.  This mode can be thought of as an extremely weak version
43 > *   of a read-lock, that can be broken by a writer at any time.  The
44 > *   use of optimistic mode for short read-only code segments often
45 > *   reduces contention and improves throughput.  However, its use is
46 > *   inherently fragile.  Optimistic read sections should only read
47 > *   fields and hold them in local variables for later use after
48 > *   validation. Fields read while in optimistic mode may be wildly
49 > *   inconsistent, so usage applies only when you are familiar enough
50 > *   with data representations to check consistency and/or repeatedly
51 > *   invoke method {@code validate()}.  For example, such steps are
52 > *   typically required when first reading an object or array
53 > *   reference, and then accessing one of its fields, elements or
54 > *   methods. </li>
55   *
56   * </ul>
57   *
58   * <p>This class also supports methods that conditionally provide
59   * conversions across the three modes. For example, method {@link
60   * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
61 < * valid write stamp if (1) already in writing mode (2) in reading
61 > * a valid write stamp if (1) already in writing mode (2) in reading
62   * mode and there are no other readers or (3) in optimistic mode and
63   * the lock is available. The forms of these methods are designed to
64   * help reduce some of the code bloat that otherwise occurs in
65   * retry-based designs.
66   *
67 < * <p>StampedLocks are designed for use in a different (and generally
68 < * narrower) range of contexts than most other locks: They are not
69 < * reentrant, so locked bodies should not call other unknown methods
70 < * that may try to re-acquire locks (although you may pass a stamp to
71 < * other methods that can use or convert it). Unvalidated optimistic
72 < * read sections should further not call methods that are not known to
67 > * <p>StampedLocks are designed for use as internal utilities in the
68 > * development of thread-safe components. Their use relies on
69 > * knowledge of the internal properties of the data, objects, and
70 > * methods they are protecting.  They are not reentrant, so locked
71 > * bodies should not call other unknown methods that may try to
72 > * re-acquire locks (although you may pass a stamp to other methods
73 > * that can use or convert it).  The use of read lock modes relies on
74 > * the associated code sections being side-effect-free.  Unvalidated
75 > * optimistic read sections cannot call methods that are not known to
76   * tolerate potential inconsistencies.  Stamps use finite
77   * representations, and are not cryptographically secure (i.e., a
78   * valid stamp may be guessable). Stamp values may recycle after (no
# Line 76 | Line 82 | import java.util.concurrent.TimeUnit;
82   * into initial unlocked state, so they are not useful for remote
83   * locking.
84   *
85 < * <p>The scheduling policy of StampedLock does not consistently prefer
86 < * readers over writers or vice versa.
85 > * <p>The scheduling policy of StampedLock does not consistently
86 > * prefer readers over writers or vice versa.  All "try" methods are
87 > * best-effort and do not necessarily conform to any scheduling or
88 > * fairness policy. A zero return from any "try" method for acquiring
89 > * or converting locks does not carry any information about the state
90 > * of the lock; a subsequent invocation may succeed.
91 > *
92 > * <p>Because it supports coordinated usage across multiple lock
93 > * modes, this class does not directly implement the {@link Lock} or
94 > * {@link ReadWriteLock} interfaces. However, a StampedLock may be
95 > * viewed {@link #asReadLock()}, {@link #asWriteLock()}, or {@link
96 > * #asReadWriteLock()} in applications requiring only the associated
97 > * set of functionality.
98   *
99   * <p><b>Sample Usage.</b> The following illustrates some usage idioms
100   * in a class that maintains simple two-dimensional points. The sample
# Line 87 | Line 104 | import java.util.concurrent.TimeUnit;
104   *
105   *  <pre>{@code
106   * class Point {
107 < *   private volatile double x, y;
107 > *   private double x, y;
108   *   private final StampedLock sl = new StampedLock();
109   *
110   *   void move(double deltaX, double deltaY) { // an exclusively locked method
# Line 100 | Line 117 | import java.util.concurrent.TimeUnit;
117   *     }
118   *   }
119   *
120 < *   double distanceFromOriginV1() { // A read-only method
121 < *     long stamp;
122 < *     if ((stamp = sl.tryOptimisticRead()) != 0L) { // optimistic
123 < *       double currentX = x;
124 < *       double currentY = y;
125 < *       if (sl.validate(stamp))
126 < *         return Math.sqrt(currentX * currentX + currentY * currentY);
127 < *     }
128 < *     stamp = sl.readLock(); // fall back to read lock
129 < *     try {
130 < *       double currentX = x;
114 < *       double currentY = y;
115 < *         return Math.sqrt(currentX * currentX + currentY * currentY);
116 < *     } finally {
117 < *       sl.unlockRead(stamp);
118 < *     }
119 < *   }
120 < *
121 < *   double distanceFromOriginV2() { // combines code paths
122 < *     for (long stamp = sl.optimisticRead(); ; stamp = sl.readLock()) {
123 < *       double currentX, currentY;
124 < *       try {
125 < *         currentX = x;
126 < *         currentY = y;
127 < *       } finally {
128 < *         if (sl.tryConvertToOptimisticRead(stamp) != 0L) // unlock or validate
129 < *           return Math.sqrt(currentX * currentX + currentY * currentY);
130 < *       }
120 > *   double distanceFromOrigin() { // A read-only method
121 > *     long stamp = sl.tryOptimisticRead();
122 > *     double currentX = x, currentY = y;
123 > *     if (!sl.validate(stamp)) {
124 > *        stamp = sl.readLock();
125 > *        try {
126 > *          currentX = x;
127 > *          currentY = y;
128 > *        } finally {
129 > *           sl.unlockRead(stamp);
130 > *        }
131   *     }
132 + *     return Math.sqrt(currentX * currentX + currentY * currentY);
133   *   }
134   *
135   *   void moveIfAtOrigin(double newX, double newY) { // upgrade
# Line 136 | Line 137 | import java.util.concurrent.TimeUnit;
137   *     long stamp = sl.readLock();
138   *     try {
139   *       while (x == 0.0 && y == 0.0) {
140 < *         long ws = tryConvertToWriteLock(stamp);
140 > *         long ws = sl.tryConvertToWriteLock(stamp);
141   *         if (ws != 0L) {
142   *           stamp = ws;
143   *           x = newX;
# Line 149 | Line 150 | import java.util.concurrent.TimeUnit;
150   *         }
151   *       }
152   *     } finally {
153 < *        sl.unlock(stamp);
153 > *       sl.unlock(stamp);
154   *     }
155   *   }
156   * }}</pre>
# Line 166 | Line 167 | public class StampedLock implements java
167       * http://www.lameter.com/gelato2005.pdf
168       * and elsewhere; see
169       * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html)
170 <     * Ordered RW locks (see Shirako et al
170 >     * and Ordered RW locks (see Shirako et al
171       * http://dl.acm.org/citation.cfm?id=2312015)
171     * and Phase-Fair locks (see Brandenburg & Anderson, especially
172     * http://www.cs.unc.edu/~bbb/diss/).
172       *
173       * Conceptually, the primary state of the lock includes a sequence
174       * number that is odd when write-locked and even otherwise.
# Line 177 | Line 176 | public class StampedLock implements java
176       * read-locked.  The read count is ignored when validating
177       * "optimistic" seqlock-reader-style stamps.  Because we must use
178       * a small finite number of bits (currently 7) for readers, a
179 <     * supplementatry reader overflow word is used when then number of
179 >     * supplementary reader overflow word is used when the number of
180       * readers exceeds the count field. We do this by treating the max
181       * reader count value (RBITS) as a spinlock protecting overflow
182       * updates.
183       *
184 <     * Waiting readers and writers use different queues. The writer
185 <     * queue is a modified form of CLH lock.  (For discussion of CLH,
186 <     * see the internal documentation of AbstractQueuedSynchronizer.)
187 <     * The reader "queue" is a form of Treiber stack, that supports
188 <     * simpler/faster operations because order within a queue doesn't
189 <     * matter and all are signalled at once.  However the sequence of
190 <     * threads within the queue vs the current stamp does matter (see
191 <     * Shirako et al) so each carries its incoming stamp value.
192 <     * Waiting writers never need to track sequence values, so they
193 <     * don't.
194 <     *
195 <     * These queue mechanics hardwire the scheduling policy.  Ignoring
196 <     * trylocks, cancellation, and spinning, they implement Phase-Fair
197 <     * preferences:
198 <     *   1. Unlocked writers prefer to signal waiting readers
199 <     *   2. Fully unlocked readers prefer to signal waiting writers
200 <     *   3. When read-locked and a waiting writer exists, the writer
201 <     *      is preferred to incoming readers
184 >     * Waiters use a modified form of CLH lock used in
185 >     * AbstractQueuedSynchronizer (see its internal documentation for
186 >     * a fuller account), where each node is tagged (field mode) as
187 >     * either a reader or writer. Sets of waiting readers are grouped
188 >     * (linked) under a common node (field cowait) so act as a single
189 >     * node with respect to most CLH mechanics.  By virtue of the
190 >     * queue structure, wait nodes need not actually carry sequence
191 >     * numbers; we know each is greater than its predecessor.  This
192 >     * simplifies the scheduling policy to a mainly-FIFO scheme that
193 >     * incorporates elements of Phase-Fair locks (see Brandenburg &
194 >     * Anderson, especially http://www.cs.unc.edu/~bbb/diss/).  In
195 >     * particular, we use the phase-fair anti-barging rule: If an
196 >     * incoming reader arrives while read lock is held but there is a
197 >     * queued writer, this incoming reader is queued.  (This rule is
198 >     * responsible for some of the complexity of method acquireRead,
199 >     * but without it, the lock becomes highly unfair.) Method release
200 >     * does not (and sometimes cannot) itself wake up cowaiters. This
201 >     * is done by the primary thread, but helped by any other threads
202 >     * with nothing better to do in methods acquireRead and
203 >     * acquireWrite.
204       *
205       * These rules apply to threads actually queued. All tryLock forms
206       * opportunistically try to acquire locks regardless of preference
207 <     * rules, and so may "barge" their way in.  Additionally, initial
208 <     * phases of the await* methods (invoked from readLock() and
209 <     * writeLock()) use controlled spins that have similar effect.
210 <     * Phase-fair preferences may also be broken on cancellations due
211 <     * to timeouts and interrupts.  Rule #3 (incoming readers when a
212 <     * waiting writer) is approximated with varying precision in
213 <     * different contexts -- some checks do not account for
214 <     * in-progress spins/signals, and others do not account for
215 <     * cancellations.
207 >     * rules, and so may "barge" their way in.  Randomized spinning is
208 >     * used in the acquire methods to reduce (increasingly expensive)
209 >     * context switching while also avoiding sustained memory
210 >     * thrashing among many threads.  We limit spins to the head of
211 >     * queue. A thread spin-waits up to SPINS times (where each
212 >     * iteration decreases spin count with 50% probability) before
213 >     * blocking. If, upon wakening it fails to obtain lock, and is
214 >     * still (or becomes) the first waiting thread (which indicates
215 >     * that some other thread barged and obtained lock), it escalates
216 >     * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
217 >     * continually losing to barging threads.
218 >     *
219 >     * Nearly all of these mechanics are carried out in methods
220 >     * acquireWrite and acquireRead, that, as typical of such code,
221 >     * sprawl out because actions and retries rely on consistent sets
222 >     * of locally cached reads.
223       *
224       * As noted in Boehm's paper (above), sequence validation (mainly
225       * method validate()) requires stricter ordering rules than apply
# Line 231 | Line 239 | public class StampedLock implements java
239       * be subject to future improvements.
240       */
241  
242 +    private static final long serialVersionUID = -6001602636862214147L;
243 +
244      /** Number of processors, for spin control */
245      private static final int NCPU = Runtime.getRuntime().availableProcessors();
246  
247 <    /** Maximum number of retries before blocking on acquisition */
248 <    private static final int SPINS = NCPU > 1 ? 1 << 6 : 1;
247 >    /** Maximum number of retries before enqueuing on acquisition */
248 >    private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
249 >
250 >    /** Maximum number of retries before blocking at head on acquisition */
251 >    private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
252  
253 <    /** Maximum number of retries before re-blocking on write lock */
254 <    private static final int MAX_HEAD_SPINS = NCPU > 1 ? 1 << 12 : 1;
253 >    /** Maximum number of retries before re-blocking */
254 >    private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
255  
256      /** The period for yielding when waiting for overflow spinlock */
257      private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
258  
259      /** The number of bits to use for reader count before overflowing */
260 <    private static final int  LG_READERS = 7;
260 >    private static final int LG_READERS = 7;
261  
262      // Values for lock state and stamp operations
263      private static final long RUNIT = 1L;
# Line 257 | Line 270 | public class StampedLock implements java
270      // Initial value for lock state; avoid failure value zero
271      private static final long ORIGIN = WBIT << 1;
272  
273 <    // Special value from cancelled await methods so caller can throw IE
273 >    // Special value from cancelled acquire methods so caller can throw IE
274      private static final long INTERRUPTED = 1L;
275  
276 <    // Values for writer status; order matters
276 >    // Values for node status; order matters
277      private static final int WAITING   = -1;
278      private static final int CANCELLED =  1;
279  
280 <    /** Wait nodes for readers */
281 <    static final class RNode {
282 <        final long seq;         // stamp value upon enqueue
270 <        volatile Thread waiter; // null if no longer waiting
271 <        volatile RNode next;
272 <        RNode(long s, Thread w) { seq = s; waiter = w; }
273 <    }
280 >    // Modes for nodes (int not boolean to allow arithmetic)
281 >    private static final int RMODE = 0;
282 >    private static final int WMODE = 1;
283  
284 <    /** Wait nodes for writers */
284 >    /** Wait nodes */
285      static final class WNode {
277        volatile int status;   // 0, WAITING, or CANCELLED
286          volatile WNode prev;
287          volatile WNode next;
288 <        volatile Thread thread;
289 <        WNode(Thread t, WNode p) { thread = t; prev = p; }
288 >        volatile WNode cowait;    // list of linked readers
289 >        volatile Thread thread;   // non-null while possibly parked
290 >        volatile int status;      // 0, WAITING, or CANCELLED
291 >        final int mode;           // RMODE or WMODE
292 >        WNode(int m, WNode p) { mode = m; prev = p; }
293      }
294  
295 <    /** Head of writer CLH queue */
295 >    /** Head of CLH queue */
296      private transient volatile WNode whead;
297 <    /** Tail (last) of writer CLH queue */
297 >    /** Tail (last) of CLH queue */
298      private transient volatile WNode wtail;
299 <    /** Head of read queue  */
300 <    private transient volatile RNode rhead;
301 <    /** The state of the lock -- high bits hold sequence, low bits read count */
299 >
300 >    // views
301 >    transient ReadLockView readLockView;
302 >    transient WriteLockView writeLockView;
303 >    transient ReadWriteLockView readWriteLockView;
304 >
305 >    /** Lock sequence/state */
306      private transient volatile long state;
307      /** extra reader count when state read count saturated */
308      private transient int readerOverflow;
309  
310      /**
311 <     * Creates a new lock initially in unlocked state.
311 >     * Creates a new lock, initially in unlocked state.
312       */
313      public StampedLock() {
314          state = ORIGIN;
# Line 303 | Line 318 | public class StampedLock implements java
318       * Exclusively acquires the lock, blocking if necessary
319       * until available.
320       *
321 <     * @return a stamp that can be used to unlock or convert mode.
321 >     * @return a stamp that can be used to unlock or convert mode
322       */
323      public long writeLock() {
324 <        long s, next;
325 <        if (((s = state) & ABITS) == 0L &&
326 <            U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
327 <            return next;
313 <        return awaitWrite(false, 0L);
324 >        long s, next;  // bypass acquireWrite in fully unlocked case only
325 >        return ((((s = state) & ABITS) == 0L &&
326 >                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
327 >                next : acquireWrite(false, 0L));
328      }
329  
330      /**
331       * Exclusively acquires the lock if it is immediately available.
332       *
333       * @return a stamp that can be used to unlock or convert mode,
334 <     * or zero if the lock is not available.
334 >     * or zero if the lock is not available
335       */
336      public long tryWriteLock() {
337          long s, next;
338 <        if (((s = state) & ABITS) == 0L &&
339 <            U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
340 <            return next;
327 <        return 0L;
338 >        return ((((s = state) & ABITS) == 0L &&
339 >                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
340 >                next : 0L);
341      }
342  
343      /**
344       * Exclusively acquires the lock if it is available within the
345 <     * given time and the current thread has not been interrupted
345 >     * given time and the current thread has not been interrupted.
346 >     * Behavior under timeout and interruption matches that specified
347 >     * for method {@link Lock#tryLock(long,TimeUnit)}.
348       *
349 +     * @param time the maximum time to wait for the lock
350 +     * @param unit the time unit of the {@code time} argument
351       * @return a stamp that can be used to unlock or convert mode,
352 <     * or zero if the lock is not available.
352 >     * or zero if the lock is not available
353       * @throws InterruptedException if the current thread is interrupted
354 <     * before acquiring the lock.
354 >     * before acquiring the lock
355       */
356      public long tryWriteLock(long time, TimeUnit unit)
357          throws InterruptedException {
358 <        long nanos =  unit.toNanos(time);
358 >        long nanos = unit.toNanos(time);
359          if (!Thread.interrupted()) {
360 <            long s, next, deadline;
361 <            if (((s = state) & ABITS) == 0L &&
345 <                U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
360 >            long next, deadline;
361 >            if ((next = tryWriteLock()) != 0L)
362                  return next;
363              if (nanos <= 0L)
364                  return 0L;
365              if ((deadline = System.nanoTime() + nanos) == 0L)
366                  deadline = 1L;
367 <            if ((next = awaitWrite(true, deadline)) != INTERRUPTED)
367 >            if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
368                  return next;
369          }
370          throw new InterruptedException();
# Line 357 | Line 373 | public class StampedLock implements java
373      /**
374       * Exclusively acquires the lock, blocking if necessary
375       * until available or the current thread is interrupted.
376 +     * Behavior under interruption matches that specified
377 +     * for method {@link Lock#lockInterruptibly()}.
378       *
379 <     * @return a stamp that can be used to unlock or convert mode.
379 >     * @return a stamp that can be used to unlock or convert mode
380       * @throws InterruptedException if the current thread is interrupted
381 <     * before acquiring the lock.
381 >     * before acquiring the lock
382       */
383      public long writeLockInterruptibly() throws InterruptedException {
384 <        if (!Thread.interrupted()) {
385 <            long s, next;
386 <            if (((s = state) & ABITS) == 0L &&
387 <                U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
370 <                return next;
371 <            if ((next = awaitWrite(true, 0L)) != INTERRUPTED)
372 <                return next;
373 <        }
384 >        long next;
385 >        if (!Thread.interrupted() &&
386 >            (next = acquireWrite(true, 0L)) != INTERRUPTED)
387 >            return next;
388          throw new InterruptedException();
389      }
390  
# Line 378 | Line 392 | public class StampedLock implements java
392       * Non-exclusively acquires the lock, blocking if necessary
393       * until available.
394       *
395 <     * @return a stamp that can be used to unlock or convert mode.
395 >     * @return a stamp that can be used to unlock or convert mode
396       */
397      public long readLock() {
398 <        for (;;) {
399 <            long s, m, next;
400 <            if ((m = (s = state) & ABITS) == 0L ||
401 <                (m < WBIT && whead == wtail)) {
388 <                if (m < RFULL) {
389 <                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
390 <                        return next;
391 <                }
392 <                else if ((next = tryIncReaderOverflow(s)) != 0L)
393 <                    return next;
394 <            }
395 <            else
396 <                return awaitRead(s, false, 0L);
397 <        }
398 >        long s = state, next;  // bypass acquireRead on common uncontended case
399 >        return ((whead == wtail && (s & ABITS) < RFULL &&
400 >                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
401 >                next : acquireRead(false, 0L));
402      }
403  
404      /**
405       * Non-exclusively acquires the lock if it is immediately available.
406       *
407       * @return a stamp that can be used to unlock or convert mode,
408 <     * or zero if the lock is not available.
408 >     * or zero if the lock is not available
409       */
410      public long tryReadLock() {
411          for (;;) {
# Line 419 | Line 423 | public class StampedLock implements java
423  
424      /**
425       * Non-exclusively acquires the lock if it is available within the
426 <     * given time and the current thread has not been interrupted
426 >     * given time and the current thread has not been interrupted.
427 >     * Behavior under timeout and interruption matches that specified
428 >     * for method {@link Lock#tryLock(long,TimeUnit)}.
429       *
430 +     * @param time the maximum time to wait for the lock
431 +     * @param unit the time unit of the {@code time} argument
432       * @return a stamp that can be used to unlock or convert mode,
433 <     * or zero if the lock is not available.
433 >     * or zero if the lock is not available
434       * @throws InterruptedException if the current thread is interrupted
435 <     * before acquiring the lock.
435 >     * before acquiring the lock
436       */
437      public long tryReadLock(long time, TimeUnit unit)
438          throws InterruptedException {
439 +        long s, m, next, deadline;
440          long nanos = unit.toNanos(time);
441          if (!Thread.interrupted()) {
442 <            for (;;) {
443 <                long s, m, next, deadline;
435 <                if ((m = (s = state) & ABITS) == WBIT ||
436 <                    (m != 0L && whead != wtail)) {
437 <                    if (nanos <= 0L)
438 <                        return 0L;
439 <                    if ((deadline = System.nanoTime() + nanos) == 0L)
440 <                        deadline = 1L;
441 <                    if ((next = awaitRead(s, true, deadline)) != INTERRUPTED)
442 <                        return next;
443 <                    break;
444 <                }
445 <                else if (m < RFULL) {
442 >            if ((m = (s = state) & ABITS) != WBIT) {
443 >                if (m < RFULL) {
444                      if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
445                          return next;
446                  }
447                  else if ((next = tryIncReaderOverflow(s)) != 0L)
448                      return next;
449              }
450 +            if (nanos <= 0L)
451 +                return 0L;
452 +            if ((deadline = System.nanoTime() + nanos) == 0L)
453 +                deadline = 1L;
454 +            if ((next = acquireRead(true, deadline)) != INTERRUPTED)
455 +                return next;
456          }
457          throw new InterruptedException();
458      }
# Line 456 | Line 460 | public class StampedLock implements java
460      /**
461       * Non-exclusively acquires the lock, blocking if necessary
462       * until available or the current thread is interrupted.
463 +     * Behavior under interruption matches that specified
464 +     * for method {@link Lock#lockInterruptibly()}.
465       *
466 <     * @return a stamp that can be used to unlock or convert mode.
466 >     * @return a stamp that can be used to unlock or convert mode
467       * @throws InterruptedException if the current thread is interrupted
468 <     * before acquiring the lock.
468 >     * before acquiring the lock
469       */
470      public long readLockInterruptibly() throws InterruptedException {
471 <        if (!Thread.interrupted()) {
472 <            for (;;) {
473 <                long s, next, m;
474 <                if ((m = (s = state) & ABITS) == WBIT ||
469 <                    (m != 0L && whead != wtail)) {
470 <                    if ((next = awaitRead(s, true, 0L)) != INTERRUPTED)
471 <                        return next;
472 <                    break;
473 <                }
474 <                else if (m < RFULL) {
475 <                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
476 <                        return next;
477 <                }
478 <                else if ((next = tryIncReaderOverflow(s)) != 0L)
479 <                    return next;
480 <            }
481 <        }
471 >        long next;
472 >        if (!Thread.interrupted() &&
473 >            (next = acquireRead(true, 0L)) != INTERRUPTED)
474 >            return next;
475          throw new InterruptedException();
476      }
477  
# Line 494 | Line 487 | public class StampedLock implements java
487      }
488  
489      /**
490 <     * Returns true if the lock has not been exclusively held since
491 <     * issuance of the given stamp. Always returns false if the stamp
492 <     * is zero. Always returns true if the stamp represents a
493 <     * currently held lock.
490 >     * Returns true if the lock has not been exclusively acquired
491 >     * since issuance of the given stamp. Always returns false if the
492 >     * stamp is zero. Always returns true if the stamp represents a
493 >     * currently held lock. Invoking this method with a value not
494 >     * obtained from {@link #tryOptimisticRead} or a locking method
495 >     * for this lock has no defined effect or result.
496       *
497 <     * @return true if the lock has not been exclusively held since
498 <     * issuance of the given stamp; else false
497 >     * @param stamp a stamp
498 >     * @return {@code true} if the lock has not been exclusively acquired
499 >     * since issuance of the given stamp; else false
500       */
501      public boolean validate(long stamp) {
502 +        // See above about current use of getLongVolatile here
503          return (stamp & SBITS) == (U.getLongVolatile(this, STATE) & SBITS);
504      }
505  
# Line 512 | Line 509 | public class StampedLock implements java
509       *
510       * @param stamp a stamp returned by a write-lock operation
511       * @throws IllegalMonitorStateException if the stamp does
512 <     * not match the current state of this lock.
512 >     * not match the current state of this lock
513       */
514      public void unlockWrite(long stamp) {
515 +        WNode h;
516          if (state != stamp || (stamp & WBIT) == 0L)
517              throw new IllegalMonitorStateException();
518          state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
519 <        readerPrefSignal();
519 >        if ((h = whead) != null && h.status != 0)
520 >            release(h);
521      }
522  
523      /**
524 <     * If the lock state matches the given stamp, releases
524 >     * If the lock state matches the given stamp, releases the
525       * non-exclusive lock.
526       *
527       * @param stamp a stamp returned by a read-lock operation
528       * @throws IllegalMonitorStateException if the stamp does
529 <     * not match the current state of this lock.
529 >     * not match the current state of this lock
530       */
531      public void unlockRead(long stamp) {
532 <        long s, m;
533 <        if ((stamp & RBITS) != 0L) {
534 <            while (((s = state) & SBITS) == (stamp & SBITS)) {
535 <                if ((m = s & ABITS) == 0L)
532 >        long s, m; WNode h;
533 >        for (;;) {
534 >            if (((s = state) & SBITS) != (stamp & SBITS) ||
535 >                (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
536 >                throw new IllegalMonitorStateException();
537 >            if (m < RFULL) {
538 >                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
539 >                    if (m == RUNIT && (h = whead) != null && h.status != 0)
540 >                        release(h);
541                      break;
538                else if (m < RFULL) {
539                    if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
540                        if (m == RUNIT)
541                            writerPrefSignal();
542                        return;
543                    }
542                  }
545                else if (m >= WBIT)
546                    break;
547                else if (tryDecReaderOverflow(s) != 0L)
548                    return;
543              }
544 +            else if (tryDecReaderOverflow(s) != 0L)
545 +                break;
546          }
551        throw new IllegalMonitorStateException();
547      }
548  
549      /**
# Line 557 | Line 552 | public class StampedLock implements java
552       *
553       * @param stamp a stamp returned by a lock operation
554       * @throws IllegalMonitorStateException if the stamp does
555 <     * not match the current state of this lock.
555 >     * not match the current state of this lock
556       */
557      public void unlock(long stamp) {
558 <        long a = stamp & ABITS, m, s;
558 >        long a = stamp & ABITS, m, s; WNode h;
559          while (((s = state) & SBITS) == (stamp & SBITS)) {
560              if ((m = s & ABITS) == 0L)
561                  break;
# Line 568 | Line 563 | public class StampedLock implements java
563                  if (a != m)
564                      break;
565                  state = (s += WBIT) == 0L ? ORIGIN : s;
566 <                readerPrefSignal();
566 >                if ((h = whead) != null && h.status != 0)
567 >                    release(h);
568                  return;
569              }
570              else if (a == 0L || a >= WBIT)
571                  break;
572              else if (m < RFULL) {
573                  if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
574 <                    if (m == RUNIT)
575 <                        writerPrefSignal();
574 >                    if (m == RUNIT && (h = whead) != null && h.status != 0)
575 >                        release(h);
576                      return;
577                  }
578              }
# Line 587 | Line 583 | public class StampedLock implements java
583      }
584  
585      /**
586 <     * If the lock state matches the given stamp then performs one of
586 >     * If the lock state matches the given stamp, performs one of
587       * the following actions. If the stamp represents holding a write
588 <     * lock, returns it. Or, if a read lock, if the write lock is
589 <     * available, releases the read and returns a write stamp. Or, if
590 <     * an optimistic read, returns a write stamp only if immediately
591 <     * available. This method returns zero in all other cases.
588 >     * lock, returns it.  Or, if a read lock, if the write lock is
589 >     * available, releases the read lock and returns a write stamp.
590 >     * Or, if an optimistic read, returns a write stamp only if
591 >     * immediately available. This method returns zero in all other
592 >     * cases.
593       *
594       * @param stamp a stamp
595       * @return a valid write stamp, or zero on failure
# Line 611 | Line 608 | public class StampedLock implements java
608                      break;
609                  return stamp;
610              }
611 <            else if (m == RUNIT && a != 0L && a < WBIT) {
611 >            else if (m == RUNIT && a != 0L) {
612                  if (U.compareAndSwapLong(this, STATE, s,
613                                           next = s - RUNIT + WBIT))
614                      return next;
# Line 623 | Line 620 | public class StampedLock implements java
620      }
621  
622      /**
623 <     * If the lock state matches the given stamp then performs one of
623 >     * If the lock state matches the given stamp, performs one of
624       * the following actions. If the stamp represents holding a write
625       * lock, releases it and obtains a read lock.  Or, if a read lock,
626       * returns it. Or, if an optimistic read, acquires a read lock and
# Line 634 | Line 631 | public class StampedLock implements java
631       * @return a valid read stamp, or zero on failure
632       */
633      public long tryConvertToReadLock(long stamp) {
634 <        long a = stamp & ABITS, m, s, next;
634 >        long a = stamp & ABITS, m, s, next; WNode h;
635          while (((s = state) & SBITS) == (stamp & SBITS)) {
636              if ((m = s & ABITS) == 0L) {
637                  if (a != 0L)
# Line 649 | Line 646 | public class StampedLock implements java
646              else if (m == WBIT) {
647                  if (a != m)
648                      break;
649 <                next = state = s + (WBIT + RUNIT);
650 <                readerPrefSignal();
649 >                state = next = s + (WBIT + RUNIT);
650 >                if ((h = whead) != null && h.status != 0)
651 >                    release(h);
652                  return next;
653              }
654              else if (a != 0L && a < WBIT)
# Line 672 | Line 670 | public class StampedLock implements java
670       * @return a valid optimistic read stamp, or zero on failure
671       */
672      public long tryConvertToOptimisticRead(long stamp) {
673 <        long a = stamp & ABITS, m, s, next;
674 <        while (((s = U.getLongVolatile(this, STATE)) &
675 <                SBITS) == (stamp & SBITS)) {
673 >        long a = stamp & ABITS, m, s, next; WNode h;
674 >        for (;;) {
675 >            s = U.getLongVolatile(this, STATE); // see above
676 >            if (((s = state) & SBITS) != (stamp & SBITS))
677 >                break;
678              if ((m = s & ABITS) == 0L) {
679                  if (a != 0L)
680                      break;
# Line 683 | Line 683 | public class StampedLock implements java
683              else if (m == WBIT) {
684                  if (a != m)
685                      break;
686 <                next = state = (s += WBIT) == 0L ? ORIGIN : s;
687 <                readerPrefSignal();
686 >                state = next = (s += WBIT) == 0L ? ORIGIN : s;
687 >                if ((h = whead) != null && h.status != 0)
688 >                    release(h);
689                  return next;
690              }
691              else if (a == 0L || a >= WBIT)
692                  break;
693              else if (m < RFULL) {
694                  if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
695 <                    if (m == RUNIT)
696 <                        writerPrefSignal();
695 >                    if (m == RUNIT && (h = whead) != null && h.status != 0)
696 >                        release(h);
697                      return next & SBITS;
698                  }
699              }
# Line 707 | Line 708 | public class StampedLock implements java
708       * stamp value. This method may be useful for recovery after
709       * errors.
710       *
711 <     * @return true if the lock was held, else false.
711 >     * @return {@code true} if the lock was held, else false
712       */
713      public boolean tryUnlockWrite() {
714 <        long s;
714 >        long s; WNode h;
715          if (((s = state) & WBIT) != 0L) {
716              state = (s += WBIT) == 0L ? ORIGIN : s;
717 <            readerPrefSignal();
717 >            if ((h = whead) != null && h.status != 0)
718 >                release(h);
719              return true;
720          }
721          return false;
# Line 724 | Line 726 | public class StampedLock implements java
726       * requiring a stamp value. This method may be useful for recovery
727       * after errors.
728       *
729 <     * @return true if the read lock was held, else false.
729 >     * @return {@code true} if the read lock was held, else false
730       */
731      public boolean tryUnlockRead() {
732 <        long s, m;
732 >        long s, m; WNode h;
733          while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
734              if (m < RFULL) {
735                  if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
736 <                    if (m == RUNIT)
737 <                        writerPrefSignal();
736 >                    if (m == RUNIT && (h = whead) != null && h.status != 0)
737 >                        release(h);
738                      return true;
739                  }
740              }
# Line 742 | Line 744 | public class StampedLock implements java
744          return false;
745      }
746  
747 +    // status monitoring methods
748 +
749      /**
750 <     * Returns true if the lock is currently held exclusively.
750 >     * Returns combined state-held and overflow read count for given
751 >     * state s.
752 >     */
753 >    private int getReadLockCount(long s) {
754 >        long readers;
755 >        if ((readers = s & RBITS) >= RFULL)
756 >            readers = RFULL + readerOverflow;
757 >        return (int) readers;
758 >    }
759 >
760 >    /**
761 >     * Returns {@code true} if the lock is currently held exclusively.
762       *
763 <     * @return true if the lock is currently held exclusively
763 >     * @return {@code true} if the lock is currently held exclusively
764       */
765      public boolean isWriteLocked() {
766          return (state & WBIT) != 0L;
767      }
768  
769      /**
770 <     * Returns true if the lock is currently held non-exclusively.
770 >     * Returns {@code true} if the lock is currently held non-exclusively.
771       *
772 <     * @return true if the lock is currently held non-exclusively
772 >     * @return {@code true} if the lock is currently held non-exclusively
773       */
774      public boolean isReadLocked() {
775 <        long m;
776 <        return (m = state & ABITS) > 0L && m < WBIT;
775 >        return (state & RBITS) != 0L;
776 >    }
777 >
778 >    /**
779 >     * Queries the number of read locks held for this lock. This
780 >     * method is designed for use in monitoring system state, not for
781 >     * synchronization control.
782 >     * @return the number of read locks held
783 >     */
784 >    public int getReadLockCount() {
785 >        return getReadLockCount(state);
786 >    }
787 >
788 >    /**
789 >     * Returns a string identifying this lock, as well as its lock
790 >     * state.  The state, in brackets, includes the String {@code
791 >     * "Unlocked"} or the String {@code "Write-locked"} or the String
792 >     * {@code "Read-locks:"} followed by the current number of
793 >     * read-locks held.
794 >     *
795 >     * @return a string identifying this lock, as well as its lock state
796 >     */
797 >    public String toString() {
798 >        long s = state;
799 >        return super.toString() +
800 >            ((s & ABITS) == 0L ? "[Unlocked]" :
801 >             (s & WBIT) != 0L ? "[Write-locked]" :
802 >             "[Read-locks:" + getReadLockCount(s) + "]");
803 >    }
804 >
805 >    // views
806 >
807 >    /**
808 >     * Returns a plain {@link Lock} view of this StampedLock in which
809 >     * the {@link Lock#lock} method is mapped to {@link #readLock},
810 >     * and similarly for other methods. The returned Lock does not
811 >     * support a {@link Condition}; method {@link
812 >     * Lock#newCondition()} throws {@code
813 >     * UnsupportedOperationException}.
814 >     *
815 >     * @return the lock
816 >     */
817 >    public Lock asReadLock() {
818 >        ReadLockView v;
819 >        return ((v = readLockView) != null ? v :
820 >                (readLockView = new ReadLockView()));
821 >    }
822 >
823 >    /**
824 >     * Returns a plain {@link Lock} view of this StampedLock in which
825 >     * the {@link Lock#lock} method is mapped to {@link #writeLock},
826 >     * and similarly for other methods. The returned Lock does not
827 >     * support a {@link Condition}; method {@link
828 >     * Lock#newCondition()} throws {@code
829 >     * UnsupportedOperationException}.
830 >     *
831 >     * @return the lock
832 >     */
833 >    public Lock asWriteLock() {
834 >        WriteLockView v;
835 >        return ((v = writeLockView) != null ? v :
836 >                (writeLockView = new WriteLockView()));
837 >    }
838 >
839 >    /**
840 >     * Returns a {@link ReadWriteLock} view of this StampedLock in
841 >     * which the {@link ReadWriteLock#readLock()} method is mapped to
842 >     * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to
843 >     * {@link #asWriteLock()}.
844 >     *
845 >     * @return the lock
846 >     */
847 >    public ReadWriteLock asReadWriteLock() {
848 >        ReadWriteLockView v;
849 >        return ((v = readWriteLockView) != null ? v :
850 >                (readWriteLockView = new ReadWriteLockView()));
851 >    }
852 >
853 >    // view classes
854 >
855 >    final class ReadLockView implements Lock {
856 >        public void lock() { readLock(); }
857 >        public void lockInterruptibly() throws InterruptedException {
858 >            readLockInterruptibly();
859 >        }
860 >        public boolean tryLock() { return tryReadLock() != 0L; }
861 >        public boolean tryLock(long time, TimeUnit unit)
862 >            throws InterruptedException {
863 >            return tryReadLock(time, unit) != 0L;
864 >        }
865 >        public void unlock() { unstampedUnlockRead(); }
866 >        public Condition newCondition() {
867 >            throw new UnsupportedOperationException();
868 >        }
869 >    }
870 >
871 >    final class WriteLockView implements Lock {
872 >        public void lock() { writeLock(); }
873 >        public void lockInterruptibly() throws InterruptedException {
874 >            writeLockInterruptibly();
875 >        }
876 >        public boolean tryLock() { return tryWriteLock() != 0L; }
877 >        public boolean tryLock(long time, TimeUnit unit)
878 >            throws InterruptedException {
879 >            return tryWriteLock(time, unit) != 0L;
880 >        }
881 >        public void unlock() { unstampedUnlockWrite(); }
882 >        public Condition newCondition() {
883 >            throw new UnsupportedOperationException();
884 >        }
885 >    }
886 >
887 >    final class ReadWriteLockView implements ReadWriteLock {
888 >        public Lock readLock() { return asReadLock(); }
889 >        public Lock writeLock() { return asWriteLock(); }
890 >    }
891 >
892 >    // Unlock methods without stamp argument checks for view classes.
893 >    // Needed because view-class lock methods throw away stamps.
894 >
895 >    final void unstampedUnlockWrite() {
896 >        WNode h; long s;
897 >        if (((s = state) & WBIT) == 0L)
898 >            throw new IllegalMonitorStateException();
899 >        state = (s += WBIT) == 0L ? ORIGIN : s;
900 >        if ((h = whead) != null && h.status != 0)
901 >            release(h);
902 >    }
903 >
904 >    final void unstampedUnlockRead() {
905 >        for (;;) {
906 >            long s, m; WNode h;
907 >            if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
908 >                throw new IllegalMonitorStateException();
909 >            else if (m < RFULL) {
910 >                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
911 >                    if (m == RUNIT && (h = whead) != null && h.status != 0)
912 >                        release(h);
913 >                    break;
914 >                }
915 >            }
916 >            else if (tryDecReaderOverflow(s) != 0L)
917 >                break;
918 >        }
919      }
920  
921      private void readObject(java.io.ObjectInputStream s)
# Line 773 | Line 930 | public class StampedLock implements java
930       * Tries to increment readerOverflow by first setting state
931       * access bits value to RBITS, indicating hold of spinlock,
932       * then updating, then releasing.
933 <     * @param stamp, assumed that (stamp & ABITS) >= RFULL
933 >     *
934 >     * @param s a reader overflow stamp: (s & ABITS) >= RFULL
935       * @return new stamp on success, else zero
936       */
937      private long tryIncReaderOverflow(long s) {
938 +        // assert (s & ABITS) >= RFULL;
939          if ((s & ABITS) == RFULL) {
940              if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
941                  ++readerOverflow;
# Line 792 | Line 951 | public class StampedLock implements java
951  
952      /**
953       * Tries to decrement readerOverflow.
954 <     * @param stamp, assumed that (stamp & ABITS) >= RFULL
954 >     *
955 >     * @param s a reader overflow stamp: (s & ABITS) >= RFULL
956       * @return new stamp on success, else zero
957       */
958      private long tryDecReaderOverflow(long s) {
959 +        // assert (s & ABITS) >= RFULL;
960          if ((s & ABITS) == RFULL) {
961              if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
962                  int r; long next;
# Line 815 | Line 976 | public class StampedLock implements java
976          return 0L;
977      }
978  
979 <    /*
980 <     * The two versions of signal implement the phase-fair policy.
981 <     * They include almost the same code, but repacked in different
982 <     * ways.  Integrating the policy with the mechanics eliminates
983 <     * state rechecks that would be needed with separate reader and
984 <     * writer signal methods.  Both methods assume that they are
985 <     * called when the lock is last known to be available, and
986 <     * continue until the lock is unavailable, or at least one thread
987 <     * is signalled, or there are no more waiting threads.  Signalling
988 <     * a reader entails popping (CASing) from rhead and unparking
989 <     * unless the thread already cancelled (indicated by a null waiter
829 <     * field). Signalling a writer requires finding the first node,
830 <     * i.e., the successor of whead. This is normally just head.next,
831 <     * but may require traversal from wtail if next pointers are
832 <     * lagging. These methods may fail to wake up an acquiring thread
833 <     * when one or more have been cancelled, but the cancel methods
834 <     * themselves provide extra safeguards to ensure liveness.
835 <     */
836 <
837 <    private void readerPrefSignal() {
838 <        boolean readers = false;
839 <        RNode p; WNode h, q; long s; Thread w;
840 <        while ((p = rhead) != null) {
841 <            if (((s = state) & WBIT) != 0L)
842 <                return;
843 <            if (p.seq == (s & SBITS))
844 <                break;
845 <            readers = true;
846 <            if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
847 <                (w = p.waiter) != null &&
848 <                U.compareAndSwapObject(p, WAITER, w, null))
849 <                U.unpark(w);
850 <        }
851 <        if (!readers && (state & ABITS) == 0L &&
852 <            (h = whead) != null && h.status != 0) {
853 <            U.compareAndSwapInt(h, STATUS, WAITING, 0);
854 <            if ((q = h.next) == null || q.status == CANCELLED) {
855 <                q = null;
856 <                for (WNode t = wtail; t != null && t != h; t = t.prev)
857 <                    if (t.status <= 0)
858 <                        q = t;
859 <            }
860 <            if (q != null && (w = q.thread) != null)
861 <                U.unpark(w);
862 <        }
863 <    }
864 <
865 <    private void writerPrefSignal() {
866 <        RNode p; WNode h, q; long s; Thread w;
867 <        if ((h = whead) != null && h.status != 0) {
868 <            U.compareAndSwapInt(h, STATUS, WAITING, 0);
979 >    /**
980 >     * Wakes up the successor of h (normally whead). This is normally
981 >     * just h.next, but may require traversal from wtail if next
982 >     * pointers are lagging. This may fail to wake up an acquiring
983 >     * thread when one or more have been cancelled, but the cancel
984 >     * methods themselves provide extra safeguards to ensure liveness.
985 >     */
986 >    private void release(WNode h) {
987 >        if (h != null) {
988 >            WNode q; Thread w;
989 >            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
990              if ((q = h.next) == null || q.status == CANCELLED) {
870                q = null;
991                  for (WNode t = wtail; t != null && t != h; t = t.prev)
992                      if (t.status <= 0)
993                          q = t;
# Line 875 | Line 995 | public class StampedLock implements java
995              if (q != null && (w = q.thread) != null)
996                  U.unpark(w);
997          }
878        else {
879            while ((p = rhead) != null && ((s = state) & WBIT) == 0L &&
880                   p.seq != (s & SBITS)) {
881                if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
882                    (w = p.waiter) != null &&
883                    U.compareAndSwapObject(p, WAITER, w, null))
884                    U.unpark(w);
885            }
886        }
998      }
999  
1000      /**
1001 <     * RNG for local spins. The first call from await{Read,Write}
891 <     * produces a thread-local value. Unless zero, subsequent calls
892 <     * use an xorShift to further reduce memory traffic.  Both await
893 <     * methods use a similar spin strategy: If associated queue
894 <     * appears to be empty, then the thread spin-waits up to SPINS
895 <     * times before enqueing, and then, if the first thread to be
896 <     * enqueued, spins again up to SPINS times before blocking. If,
897 <     * upon wakening it fails to obtain lock, and is still (or
898 <     * becomes) the first waiting thread (which indicates that some
899 <     * other thread barged and obtained lock), it escalates spins (up
900 <     * to MAX_HEAD_SPINS) to reduce the likelihood of continually
901 <     * losing to barging threads.
902 <     */
903 <    private static int nextRandom(int r) {
904 <        if (r == 0)
905 <            return ThreadLocalRandom.current().nextInt();
906 <        r ^= r << 1; // xorshift
907 <        r ^= r >>> 3;
908 <        r ^= r << 10;
909 <        return r;
910 <    }
911 <
912 <    /**
913 <     * Possibly spins trying to obtain write lock, then enqueues and
914 <     * blocks while not head of write queue or cannot aquire lock,
915 <     * possibly spinning when at head; cancelling on timeout or
916 <     * interrupt.
1001 >     * See above for explanation.
1002       *
1003       * @param interruptible true if should check interrupts and if so
1004       * return INTERRUPTED
1005       * @param deadline if nonzero, the System.nanoTime value to timeout
1006 <     * at (and return zero).
1006 >     * at (and return zero)
1007 >     * @return next state, or INTERRUPTED
1008       */
1009 <    private long awaitWrite(boolean interruptible, long deadline) {
1010 <        WNode node = null;
1011 <        for (int r = 0, spins = -1;;) {
1012 <            WNode p; long s, next;
1013 <            if (((s = state) & ABITS) == 0L) {
1014 <                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
1015 <                    return next;
1009 >    private long acquireWrite(boolean interruptible, long deadline) {
1010 >        WNode node = null, p;
1011 >        for (int spins = -1;;) { // spin while enqueuing
1012 >            long m, s, ns;
1013 >            if ((m = (s = state) & ABITS) == 0L) {
1014 >                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
1015 >                    return ns;
1016              }
1017              else if (spins < 0)
1018 <                spins = whead == wtail ? SPINS : 0;
1018 >                spins = (m == WBIT && wtail == whead) ? SPINS : 0;
1019              else if (spins > 0) {
1020 <                if ((r = nextRandom(r)) >= 0)
1020 >                if (ThreadLocalRandom.current().nextInt() >= 0)
1021                      --spins;
1022              }
1023              else if ((p = wtail) == null) { // initialize queue
1024 <                if (U.compareAndSwapObject(this, WHEAD, null,
1025 <                                           new WNode(null, null)))
1026 <                    wtail = whead;
1024 >                WNode hd = new WNode(WMODE, null);
1025 >                if (U.compareAndSwapObject(this, WHEAD, null, hd))
1026 >                    wtail = hd;
1027              }
1028              else if (node == null)
1029 <                node = new WNode(Thread.currentThread(), p);
1029 >                node = new WNode(WMODE, p);
1030              else if (node.prev != p)
1031                  node.prev = p;
1032              else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
1033                  p.next = node;
1034 <                for (int headSpins = SPINS;;) {
1035 <                    WNode np; int ps;
1036 <                    if ((np = node.prev) != p && np != null)
1037 <                        (p = np).next = node; // stale
1038 <                    if (p == whead) {
1039 <                        for (int k = headSpins;;) {
1040 <                            if (((s = state) & ABITS) == 0L) {
1041 <                                if (U.compareAndSwapLong(this, STATE,
1042 <                                                         s, next = s + WBIT)) {
1043 <                                    whead = node;
1044 <                                    node.thread = null;
1045 <                                    node.prev = null;
1046 <                                    return next;
1047 <                                }
1048 <                                break;
1049 <                            }
1050 <                            if ((r = nextRandom(r)) >= 0 && --k <= 0)
1051 <                                break;
1034 >                break;
1035 >            }
1036 >        }
1037 >
1038 >        for (int spins = -1;;) {
1039 >            WNode h, np, pp; int ps;
1040 >            if ((h = whead) == p) {
1041 >                if (spins < 0)
1042 >                    spins = HEAD_SPINS;
1043 >                else if (spins < MAX_HEAD_SPINS)
1044 >                    spins <<= 1;
1045 >                for (int k = spins;;) { // spin at head
1046 >                    long s, ns;
1047 >                    if (((s = state) & ABITS) == 0L) {
1048 >                        if (U.compareAndSwapLong(this, STATE, s,
1049 >                                                 ns = s + WBIT)) {
1050 >                            whead = node;
1051 >                            node.prev = null;
1052 >                            return ns;
1053                          }
967                        if (headSpins < MAX_HEAD_SPINS)
968                            headSpins <<= 1;
1054                      }
1055 <                    if ((ps = p.status) == 0)
1056 <                        U.compareAndSwapInt(p, STATUS, 0, WAITING);
1057 <                    else if (ps == CANCELLED)
1058 <                        node.prev = p.prev;
1059 <                    else {
1060 <                        long time; // 0 argument to park means no timeout
1061 <                        if (deadline == 0L)
1062 <                            time = 0L;
1063 <                        else if ((time = deadline - System.nanoTime()) <= 0L)
1064 <                            return cancelWriter(node, false);
1065 <                        if (node.prev == p && p.status == WAITING &&
1066 <                            (p != whead || (state & WBIT) != 0L)) { // recheck
1067 <                            U.park(false, time);
1068 <                            if (interruptible && Thread.interrupted())
1069 <                                return cancelWriter(node, true);
1070 <                        }
1055 >                    else if (ThreadLocalRandom.current().nextInt() >= 0 &&
1056 >                             --k <= 0)
1057 >                        break;
1058 >                }
1059 >            }
1060 >            else if (h != null) { // help release stale waiters
1061 >                WNode c; Thread w;
1062 >                while ((c = h.cowait) != null) {
1063 >                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1064 >                        (w = c.thread) != null)
1065 >                        U.unpark(w);
1066 >                }
1067 >            }
1068 >            if (whead == h) {
1069 >                if ((np = node.prev) != p) {
1070 >                    if (np != null)
1071 >                        (p = np).next = node;   // stale
1072 >                }
1073 >                else if ((ps = p.status) == 0)
1074 >                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
1075 >                else if (ps == CANCELLED) {
1076 >                    if ((pp = p.prev) != null) {
1077 >                        node.prev = pp;
1078 >                        pp.next = node;
1079                      }
1080                  }
1081 +                else {
1082 +                    long time; // 0 argument to park means no timeout
1083 +                    if (deadline == 0L)
1084 +                        time = 0L;
1085 +                    else if ((time = deadline - System.nanoTime()) <= 0L)
1086 +                        return cancelWaiter(node, node, false);
1087 +                    Thread wt = Thread.currentThread();
1088 +                    U.putObject(wt, PARKBLOCKER, this);
1089 +                    node.thread = wt;
1090 +                    if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
1091 +                        whead == h && node.prev == p)
1092 +                        U.park(false, time);  // emulate LockSupport.park
1093 +                    node.thread = null;
1094 +                    U.putObject(wt, PARKBLOCKER, null);
1095 +                    if (interruptible && Thread.interrupted())
1096 +                        return cancelWaiter(node, node, true);
1097 +                }
1098              }
1099          }
1100      }
1101  
1102      /**
1103 <     * If node non-null, forces cancel status and unsplices from queue
1104 <     * if possible. This is a streamlined variant of cancellation
1105 <     * methods in AbstractQueuedSynchronizer that includes a detailed
1106 <     * explanation.
1107 <     */
1108 <    private long cancelWriter(WNode node, boolean interrupted) {
1109 <        WNode pred;
1110 <        if (node != null && (pred = node.prev) != null) {
1111 <            WNode pp;
1112 <            node.thread = null;
1113 <            while (pred.status == CANCELLED && (pp = pred.prev) != null)
1114 <                pred = node.prev = pp;
1115 <            WNode predNext = pred.next;
1116 <            node.status = CANCELLED;
1117 <            if (predNext != null) {
1118 <                Thread w = null;
1119 <                WNode succ = node.next;
1120 <                while (succ != null && succ.status == CANCELLED)
1121 <                    succ = succ.next;
1122 <                if (succ != null)
1123 <                    w = succ.thread;
1124 <                else if (node == wtail)
1125 <                    U.compareAndSwapObject(this, WTAIL, node, pred);
1126 <                U.compareAndSwapObject(pred, WNEXT, predNext, succ);
1127 <                if (w != null)
1128 <                    U.unpark(w);
1129 <            }
1130 <        }
1131 <        writerPrefSignal();
1132 <        return (interrupted || Thread.interrupted())? INTERRUPTED : 0L;
1133 <    }
1134 <
1025 <    /*
1026 <     * Waits for read lock or timeout or interrupt. The form of
1027 <     * awaitRead differs from awaitWrite mainly because it must
1028 <     * restart (with a new wait node) if the thread was unqueued and
1029 <     * unparked but could not the obtain lock.  We also need to help
1030 <     * with preference rules by not trying to acquire the lock before
1031 <     * enqueuing if there is a known waiting writer, but also helping
1032 <     * to release those threads that are still queued from the last
1033 <     * release.
1034 <     */
1035 <    private long awaitRead(long stamp, boolean interruptible, long deadline) {
1036 <        long seq = stamp & SBITS;
1037 <        RNode node = null;
1038 <        boolean queued = false;
1039 <        for (int r = 0, headSpins = SPINS, spins = -1;;) {
1040 <            long s, m, next; RNode p; WNode wh; Thread w;
1041 <            if ((m = (s = state) & ABITS) != WBIT &&
1042 <                ((s & SBITS) != seq || (wh = whead) == null ||
1043 <                 wh.status == 0)) {
1044 <                if (m < RFULL ?
1045 <                    U.compareAndSwapLong(this, STATE, s, next = s + RUNIT) :
1046 <                    (next = tryIncReaderOverflow(s)) != 0L) {
1047 <                    if (node != null && (w = node.waiter) != null)
1048 <                        U.compareAndSwapObject(node, WAITER, w, null);
1049 <                    if ((p = rhead) != null && (s & SBITS) != p.seq &&
1050 <                        U.compareAndSwapObject(this, RHEAD, p, p.next) &&
1051 <                        (w = p.waiter) != null &&
1052 <                        U.compareAndSwapObject(p, WAITER, w, null))
1053 <                        U.unpark(w); // help signal other waiters
1054 <                    return next;
1103 >     * See above for explanation.
1104 >     *
1105 >     * @param interruptible true if should check interrupts and if so
1106 >     * return INTERRUPTED
1107 >     * @param deadline if nonzero, the System.nanoTime value to timeout
1108 >     * at (and return zero)
1109 >     * @return next state, or INTERRUPTED
1110 >     */
1111 >    private long acquireRead(boolean interruptible, long deadline) {
1112 >        WNode node = null, p;
1113 >        for (int spins = -1;;) {
1114 >            WNode h;
1115 >            if ((h = whead) == (p = wtail)) {
1116 >                for (long m, s, ns;;) {
1117 >                    if ((m = (s = state) & ABITS) < RFULL ?
1118 >                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
1119 >                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
1120 >                        return ns;
1121 >                    else if (m >= WBIT) {
1122 >                        if (spins > 0) {
1123 >                            if (ThreadLocalRandom.current().nextInt() >= 0)
1124 >                                --spins;
1125 >                        }
1126 >                        else {
1127 >                            if (spins == 0) {
1128 >                                WNode nh = whead, np = wtail;
1129 >                                if ((nh == h && np == p) || (h = nh) != (p = np))
1130 >                                    break;
1131 >                            }
1132 >                            spins = SPINS;
1133 >                        }
1134 >                    }
1135                  }
1136              }
1137 <            else if (m != WBIT && (p = rhead) != null &&
1138 <                     (s & SBITS) != p.seq) { // help release old readers
1139 <                if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
1140 <                    (w = p.waiter) != null &&
1061 <                    U.compareAndSwapObject(p, WAITER, w, null))
1062 <                    U.unpark(w);
1063 <            }
1064 <            else if (queued && node != null && node.waiter == null) {
1065 <                node = null;    // restart
1066 <                queued = false;
1067 <                spins = -1;
1068 <            }
1069 <            else if (spins < 0) {
1070 <                if (rhead != node)
1071 <                    spins = 0;
1072 <                else if ((spins = headSpins) < MAX_HEAD_SPINS && node != null)
1073 <                    headSpins <<= 1;
1074 <            }
1075 <            else if (spins > 0) {
1076 <                if ((r = nextRandom(r)) >= 0)
1077 <                    --spins;
1137 >            if (p == null) { // initialize queue
1138 >                WNode hd = new WNode(WMODE, null);
1139 >                if (U.compareAndSwapObject(this, WHEAD, null, hd))
1140 >                    wtail = hd;
1141              }
1142              else if (node == null)
1143 <                node = new RNode(seq, Thread.currentThread());
1144 <            else if (!queued) {
1145 <                if (queued = U.compareAndSwapObject(this, RHEAD,
1146 <                                                    node.next = rhead, node))
1147 <                    spins = -1;
1143 >                node = new WNode(RMODE, p);
1144 >            else if (h == p || p.mode != RMODE) {
1145 >                if (node.prev != p)
1146 >                    node.prev = p;
1147 >                else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
1148 >                    p.next = node;
1149 >                    break;
1150 >                }
1151              }
1152 +            else if (!U.compareAndSwapObject(p, WCOWAIT,
1153 +                                             node.cowait = p.cowait, node))
1154 +                node.cowait = null;
1155              else {
1156 <                long time;
1157 <                if (deadline == 0L)
1158 <                    time = 0L;
1159 <                else if ((time = deadline - System.nanoTime()) <= 0L)
1160 <                    return cancelReader(node, false);
1161 <                if ((state & WBIT) != 0L && node.waiter != null) { // recheck
1162 <                    U.park(false, time);
1163 <                    if (interruptible && Thread.interrupted())
1164 <                        return cancelReader(node, true);
1156 >                for (;;) {
1157 >                    WNode pp, c; Thread w;
1158 >                    if ((h = whead) != null && (c = h.cowait) != null &&
1159 >                        U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1160 >                        (w = c.thread) != null) // help release
1161 >                        U.unpark(w);
1162 >                    if (h == (pp = p.prev) || h == p || pp == null) {
1163 >                        long m, s, ns;
1164 >                        do {
1165 >                            if ((m = (s = state) & ABITS) < RFULL ?
1166 >                                U.compareAndSwapLong(this, STATE, s,
1167 >                                                     ns = s + RUNIT) :
1168 >                                (m < WBIT &&
1169 >                                 (ns = tryIncReaderOverflow(s)) != 0L))
1170 >                                return ns;
1171 >                        } while (m < WBIT);
1172 >                    }
1173 >                    if (whead == h && p.prev == pp) {
1174 >                        long time;
1175 >                        if (pp == null || h == p || p.status > 0) {
1176 >                            node = null; // throw away
1177 >                            break;
1178 >                        }
1179 >                        if (deadline == 0L)
1180 >                            time = 0L;
1181 >                        else if ((time = deadline - System.nanoTime()) <= 0L)
1182 >                            return cancelWaiter(node, p, false);
1183 >                        Thread wt = Thread.currentThread();
1184 >                        U.putObject(wt, PARKBLOCKER, this);
1185 >                        node.thread = wt;
1186 >                        if ((h != pp || (state & ABITS) == WBIT) &&
1187 >                            whead == h && p.prev == pp)
1188 >                            U.park(false, time);
1189 >                        node.thread = null;
1190 >                        U.putObject(wt, PARKBLOCKER, null);
1191 >                        if (interruptible && Thread.interrupted())
1192 >                            return cancelWaiter(node, p, true);
1193 >                    }
1194                  }
1195              }
1196          }
1099    }
1197  
1198 <    /**
1199 <     * If node non-null, forces cancel status and unsplices from queue
1200 <     * if possible, by traversing entire queue looking for cancelled
1201 <     * nodes, cleaning out all at head, but stopping upon first
1202 <     * encounter otherwise.
1203 <     */
1204 <    private long cancelReader(RNode node, boolean interrupted) {
1205 <        Thread w;
1206 <        if (node != null && (w = node.waiter) != null &&
1207 <            U.compareAndSwapObject(node, WAITER, w, null)) {
1208 <            for (RNode pred = null, p = rhead; p != null;) {
1209 <                RNode q = p.next;
1210 <                if (p.waiter == null) {
1211 <                    if (pred == null) {
1212 <                        U.compareAndSwapObject(this, RHEAD, p, q);
1213 <                        p = rhead;
1198 >        for (int spins = -1;;) {
1199 >            WNode h, np, pp; int ps;
1200 >            if ((h = whead) == p) {
1201 >                if (spins < 0)
1202 >                    spins = HEAD_SPINS;
1203 >                else if (spins < MAX_HEAD_SPINS)
1204 >                    spins <<= 1;
1205 >                for (int k = spins;;) { // spin at head
1206 >                    long m, s, ns;
1207 >                    if ((m = (s = state) & ABITS) < RFULL ?
1208 >                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
1209 >                        (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
1210 >                        WNode c; Thread w;
1211 >                        whead = node;
1212 >                        node.prev = null;
1213 >                        while ((c = node.cowait) != null) {
1214 >                            if (U.compareAndSwapObject(node, WCOWAIT,
1215 >                                                       c, c.cowait) &&
1216 >                                (w = c.thread) != null)
1217 >                                U.unpark(w);
1218 >                        }
1219 >                        return ns;
1220                      }
1221 <                    else {
1222 <                        U.compareAndSwapObject(pred, RNEXT, p, q);
1221 >                    else if (m >= WBIT &&
1222 >                             ThreadLocalRandom.current().nextInt() >= 0 && --k <= 0)
1223                          break;
1224 +                }
1225 +            }
1226 +            else if (h != null) {
1227 +                WNode c; Thread w;
1228 +                while ((c = h.cowait) != null) {
1229 +                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1230 +                        (w = c.thread) != null)
1231 +                        U.unpark(w);
1232 +                }
1233 +            }
1234 +            if (whead == h) {
1235 +                if ((np = node.prev) != p) {
1236 +                    if (np != null)
1237 +                        (p = np).next = node;   // stale
1238 +                }
1239 +                else if ((ps = p.status) == 0)
1240 +                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
1241 +                else if (ps == CANCELLED) {
1242 +                    if ((pp = p.prev) != null) {
1243 +                        node.prev = pp;
1244 +                        pp.next = node;
1245                      }
1246                  }
1247                  else {
1248 <                    pred = p;
1248 >                    long time;
1249 >                    if (deadline == 0L)
1250 >                        time = 0L;
1251 >                    else if ((time = deadline - System.nanoTime()) <= 0L)
1252 >                        return cancelWaiter(node, node, false);
1253 >                    Thread wt = Thread.currentThread();
1254 >                    U.putObject(wt, PARKBLOCKER, this);
1255 >                    node.thread = wt;
1256 >                    if (p.status < 0 &&
1257 >                        (p != h || (state & ABITS) == WBIT) &&
1258 >                        whead == h && node.prev == p)
1259 >                        U.park(false, time);
1260 >                    node.thread = null;
1261 >                    U.putObject(wt, PARKBLOCKER, null);
1262 >                    if (interruptible && Thread.interrupted())
1263 >                        return cancelWaiter(node, node, true);
1264 >                }
1265 >            }
1266 >        }
1267 >    }
1268 >
1269 >    /**
1270 >     * If node non-null, forces cancel status and unsplices it from
1271 >     * queue if possible and wakes up any cowaiters (of the node, or
1272 >     * group, as applicable), and in any case helps release current
1273 >     * first waiter if lock is free. (Calling with null arguments
1274 >     * serves as a conditional form of release, which is not currently
1275 >     * needed but may be needed under possible future cancellation
1276 >     * policies). This is a variant of cancellation methods in
1277 >     * AbstractQueuedSynchronizer (see its detailed explanation in AQS
1278 >     * internal documentation).
1279 >     *
1280 >     * @param node if nonnull, the waiter
1281 >     * @param group either node or the group node is cowaiting with
1282 >     * @param interrupted if already interrupted
1283 >     * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
1284 >     */
1285 >    private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
1286 >        if (node != null && group != null) {
1287 >            Thread w;
1288 >            node.status = CANCELLED;
1289 >            // unsplice cancelled nodes from group
1290 >            for (WNode p = group, q; (q = p.cowait) != null;) {
1291 >                if (q.status == CANCELLED) {
1292 >                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
1293 >                    p = group; // restart
1294 >                }
1295 >                else
1296                      p = q;
1297 +            }
1298 +            if (group == node) {
1299 +                for (WNode r = group.cowait; r != null; r = r.cowait) {
1300 +                    if ((w = r.thread) != null)
1301 +                        U.unpark(w);       // wake up uncancelled co-waiters
1302 +                }
1303 +                for (WNode pred = node.prev; pred != null; ) { // unsplice
1304 +                    WNode succ, pp;        // find valid successor
1305 +                    while ((succ = node.next) == null ||
1306 +                           succ.status == CANCELLED) {
1307 +                        WNode q = null;    // find successor the slow way
1308 +                        for (WNode t = wtail; t != null && t != node; t = t.prev)
1309 +                            if (t.status != CANCELLED)
1310 +                                q = t;     // don't link if succ cancelled
1311 +                        if (succ == q ||   // ensure accurate successor
1312 +                            U.compareAndSwapObject(node, WNEXT,
1313 +                                                   succ, succ = q)) {
1314 +                            if (succ == null && node == wtail)
1315 +                                U.compareAndSwapObject(this, WTAIL, node, pred);
1316 +                            break;
1317 +                        }
1318 +                    }
1319 +                    if (pred.next == node) // unsplice pred link
1320 +                        U.compareAndSwapObject(pred, WNEXT, node, succ);
1321 +                    if (succ != null && (w = succ.thread) != null) {
1322 +                        succ.thread = null;
1323 +                        U.unpark(w);       // wake up succ to observe new pred
1324 +                    }
1325 +                    if (pred.status != CANCELLED || (pp = pred.prev) == null)
1326 +                        break;
1327 +                    node.prev = pp;        // repeat if new pred wrong/cancelled
1328 +                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
1329 +                    pred = pp;
1330                  }
1331              }
1332          }
1333 <        readerPrefSignal();
1334 <        return (interrupted || Thread.interrupted())? INTERRUPTED : 0L;
1333 >        WNode h; // Possibly release first waiter
1334 >        while ((h = whead) != null) {
1335 >            long s; WNode q; // similar to release() but check eligibility
1336 >            if ((q = h.next) == null || q.status == CANCELLED) {
1337 >                for (WNode t = wtail; t != null && t != h; t = t.prev)
1338 >                    if (t.status <= 0)
1339 >                        q = t;
1340 >            }
1341 >            if (h == whead) {
1342 >                if (q != null && h.status == 0 &&
1343 >                    ((s = state) & ABITS) != WBIT && // waiter is eligible
1344 >                    (s == 0L || q.mode == RMODE))
1345 >                    release(h);
1346 >                break;
1347 >            }
1348 >        }
1349 >        return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1350      }
1351  
1352      // Unsafe mechanics
1353      private static final sun.misc.Unsafe U;
1354      private static final long STATE;
1136    private static final long RHEAD;
1355      private static final long WHEAD;
1356      private static final long WTAIL;
1139    private static final long RNEXT;
1357      private static final long WNEXT;
1358 <    private static final long WPREV;
1359 <    private static final long WAITER;
1360 <    private static final long STATUS;
1358 >    private static final long WSTATUS;
1359 >    private static final long WCOWAIT;
1360 >    private static final long PARKBLOCKER;
1361  
1362      static {
1363          try {
1364              U = getUnsafe();
1365              Class<?> k = StampedLock.class;
1149            Class<?> rk = RNode.class;
1366              Class<?> wk = WNode.class;
1367              STATE = U.objectFieldOffset
1368                  (k.getDeclaredField("state"));
1153            RHEAD = U.objectFieldOffset
1154                (k.getDeclaredField("rhead"));
1369              WHEAD = U.objectFieldOffset
1370                  (k.getDeclaredField("whead"));
1371              WTAIL = U.objectFieldOffset
1372                  (k.getDeclaredField("wtail"));
1373 <            RNEXT = U.objectFieldOffset
1160 <                (rk.getDeclaredField("next"));
1161 <            WAITER = U.objectFieldOffset
1162 <                (rk.getDeclaredField("waiter"));
1163 <            STATUS = U.objectFieldOffset
1373 >            WSTATUS = U.objectFieldOffset
1374                  (wk.getDeclaredField("status"));
1375              WNEXT = U.objectFieldOffset
1376                  (wk.getDeclaredField("next"));
1377 <            WPREV = U.objectFieldOffset
1378 <                (wk.getDeclaredField("prev"));
1377 >            WCOWAIT = U.objectFieldOffset
1378 >                (wk.getDeclaredField("cowait"));
1379 >            Class<?> tk = Thread.class;
1380 >            PARKBLOCKER = U.objectFieldOffset
1381 >                (tk.getDeclaredField("parkBlocker"));
1382  
1383          } catch (Exception e) {
1384              throw new Error(e);
# Line 1182 | Line 1395 | public class StampedLock implements java
1395      private static sun.misc.Unsafe getUnsafe() {
1396          try {
1397              return sun.misc.Unsafe.getUnsafe();
1398 <        } catch (SecurityException se) {
1399 <            try {
1400 <                return java.security.AccessController.doPrivileged
1401 <                    (new java.security
1402 <                     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
1403 <                        public sun.misc.Unsafe run() throws Exception {
1404 <                            java.lang.reflect.Field f = sun.misc
1405 <                                .Unsafe.class.getDeclaredField("theUnsafe");
1406 <                            f.setAccessible(true);
1407 <                            return (sun.misc.Unsafe) f.get(null);
1408 <                        }});
1409 <            } catch (java.security.PrivilegedActionException e) {
1410 <                throw new RuntimeException("Could not initialize intrinsics",
1411 <                                           e.getCause());
1412 <            }
1398 >        } catch (SecurityException tryReflectionInstead) {}
1399 >        try {
1400 >            return java.security.AccessController.doPrivileged
1401 >            (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
1402 >                public sun.misc.Unsafe run() throws Exception {
1403 >                    Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
1404 >                    for (java.lang.reflect.Field f : k.getDeclaredFields()) {
1405 >                        f.setAccessible(true);
1406 >                        Object x = f.get(null);
1407 >                        if (k.isInstance(x))
1408 >                            return k.cast(x);
1409 >                    }
1410 >                    throw new NoSuchFieldError("the Unsafe");
1411 >                }});
1412 >        } catch (java.security.PrivilegedActionException e) {
1413 >            throw new RuntimeException("Could not initialize intrinsics",
1414 >                                       e.getCause());
1415          }
1416      }
1202
1417   }
1204

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines