ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
Revision: 1.36
Committed: Wed Jun 19 14:55:40 2013 UTC (10 years, 11 months ago) by dl
Branch: MAIN
Changes since 1.35: +89 -47 lines
Log Message:
Sync with jdk8 versions

File Contents

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