ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
Revision: 1.7
Committed: Fri Oct 12 23:11:14 2012 UTC (11 years, 7 months ago) by dl
Branch: MAIN
Changes since 1.6: +6 -3 lines
Log Message:
Documentation improvements

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    
9     import java.util.concurrent.ThreadLocalRandom;
10     import java.util.concurrent.TimeUnit;
11    
12     /**
13     * A capability-based lock with three modes for controlling read/write
14     * access. The state of a StampedLock consists of a version and
15     * mode. Lock acquisition methods return a stamp that represents and
16     * controls access with respect to a lock state; "try" versions of
17     * these methods may instead return the special value zero to
18     * represent failure to acquire access. Lock release and conversion
19     * methods require stamps as arguments, and fail if they do not match
20     * the state of the lock. The three modes are:
21     *
22     * <ul>
23     *
24     * <li><b>Writing.</b> Method {@link #writeLock} possibly blocks
25     * waiting for exclusive access, returning a stamp that can be used
26     * in method {@link #unlockWrite} to release the lock. Untimed and
27     * timed versions of {@code tryWriteLock} are also provided. When
28     * the lock is held in write mode, no read locks may be obtained,
29 dl 1.6 * and all optimistic read validations will fail. </li>
30 dl 1.1 *
31     * <li><b>Reading.</b> Method {@link #readLock} possibly blocks
32     * waiting for non-exclusive access, returning a stamp that can be
33     * used in method {@link #unlockRead} to release the lock. Untimed
34     * and timed versions of {@code tryReadLock} are also provided. </li>
35     *
36     * <li><b>Optimistic Reading.</b> Method {@link #tryOptimisticRead}
37     * returns a non-zero stamp only if the lock is not currently held
38     * in write mode. Method {@link #validate} returns true if the lock
39     * has not since been acquired in write mode. This mode can be
40     * thought of as an extremely weak version of a read-lock, that can
41     * be broken by a writer at any time. The use of optimistic mode
42     * for short read-only code segments often reduces contention and
43     * improves throughput. However, its use is inherently fragile.
44     * Optimistic read sections should only read fields and hold them in
45     * local variables for later use after validation. Fields read while
46     * in optimistic mode may be wildly inconsistent, so usage applies
47     * only when you are familiar enough with data representations to
48     * check consistency and/or repeatedly invoke method {@code
49     * validate()}. For example, such steps are typically required when
50     * first reading an object or array reference, and then accessing
51     * one of its fields, elements or methods. </li>
52     *
53     * </ul>
54     *
55     * <p>This class also supports methods that conditionally provide
56     * conversions across the three modes. For example, method {@link
57     * #tryConvertToWriteLock} attempts to "upgrade" a mode, returning
58     * valid write stamp if (1) already in writing mode (2) in reading
59     * mode and there are no other readers or (3) in optimistic mode and
60     * the lock is available. The forms of these methods are designed to
61     * help reduce some of the code bloat that otherwise occurs in
62     * retry-based designs.
63     *
64     * <p>StampedLocks are designed for use in a different (and generally
65     * narrower) range of contexts than most other locks: They are not
66     * reentrant, so locked bodies should not call other unknown methods
67     * that may try to re-acquire locks (although you may pass a stamp to
68     * other methods that can use or convert it). Unvalidated optimistic
69     * read sections should further not call methods that are not known to
70     * tolerate potential inconsistencies. Stamps use finite
71     * representations, and are not cryptographically secure (i.e., a
72     * valid stamp may be guessable). Stamp values may recycle after (no
73     * sooner than) one year of continuous operation. A stamp held without
74     * use or validation for longer than this period may fail to validate
75     * correctly. StampedLocks are serializable, but always deserialize
76     * into initial unlocked state, so they are not useful for remote
77     * locking.
78     *
79 dl 1.7 * <p>The scheduling policy of StampedLock does not consistently
80     * prefer readers over writers or vice versa. A zero return from any
81     * "try" method for acquiring or converting locks does carry any
82     * information about the state of the lock; a subsequent invocation
83     * may succeed.
84 dl 1.1 *
85     * <p><b>Sample Usage.</b> The following illustrates some usage idioms
86     * in a class that maintains simple two-dimensional points. The sample
87     * code illustrates some try/catch conventions even though they are
88     * not strictly needed here because no exceptions can occur in their
89     * bodies.<br>
90     *
91     * <pre>{@code
92     * class Point {
93 dl 1.6 * private double x, y;
94 dl 1.1 * private final StampedLock sl = new StampedLock();
95     *
96     * void move(double deltaX, double deltaY) { // an exclusively locked method
97     * long stamp = sl.writeLock();
98     * try {
99     * x += deltaX;
100     * y += deltaY;
101     * } finally {
102     * sl.unlockWrite(stamp);
103     * }
104     * }
105     *
106     * double distanceFromOriginV1() { // A read-only method
107     * long stamp;
108     * if ((stamp = sl.tryOptimisticRead()) != 0L) { // optimistic
109     * double currentX = x;
110     * double currentY = y;
111     * if (sl.validate(stamp))
112     * return Math.sqrt(currentX * currentX + currentY * currentY);
113     * }
114     * stamp = sl.readLock(); // fall back to read lock
115     * try {
116     * double currentX = x;
117     * double currentY = y;
118     * return Math.sqrt(currentX * currentX + currentY * currentY);
119     * } finally {
120     * sl.unlockRead(stamp);
121     * }
122     * }
123     *
124     * double distanceFromOriginV2() { // combines code paths
125 dl 1.7 * for (long stamp = sl.tryOptimisticRead(); ; stamp = sl.readLock()) {
126 dl 1.1 * double currentX, currentY;
127     * try {
128     * currentX = x;
129     * currentY = y;
130     * } finally {
131     * if (sl.tryConvertToOptimisticRead(stamp) != 0L) // unlock or validate
132     * return Math.sqrt(currentX * currentX + currentY * currentY);
133     * }
134     * }
135     * }
136     *
137     * void moveIfAtOrigin(double newX, double newY) { // upgrade
138     * // Could instead start with optimistic, not read mode
139     * long stamp = sl.readLock();
140     * try {
141     * while (x == 0.0 && y == 0.0) {
142     * long ws = tryConvertToWriteLock(stamp);
143     * if (ws != 0L) {
144     * stamp = ws;
145     * x = newX;
146     * y = newY;
147     * break;
148     * }
149     * else {
150     * sl.unlockRead(stamp);
151     * stamp = sl.writeLock();
152     * }
153     * }
154     * } finally {
155     * sl.unlock(stamp);
156     * }
157     * }
158     * }}</pre>
159     *
160     * @since 1.8
161     * @author Doug Lea
162     */
163     public class StampedLock implements java.io.Serializable {
164     /*
165     * Algorithmic notes:
166     *
167     * The design employs elements of Sequence locks
168     * (as used in linux kernels; see Lameter's
169     * http://www.lameter.com/gelato2005.pdf
170     * and elsewhere; see
171     * Boehm's http://www.hpl.hp.com/techreports/2012/HPL-2012-68.html)
172     * Ordered RW locks (see Shirako et al
173     * http://dl.acm.org/citation.cfm?id=2312015)
174     * and Phase-Fair locks (see Brandenburg & Anderson, especially
175     * http://www.cs.unc.edu/~bbb/diss/).
176     *
177     * Conceptually, the primary state of the lock includes a sequence
178     * number that is odd when write-locked and even otherwise.
179     * However, this is offset by a reader count that is non-zero when
180     * read-locked. The read count is ignored when validating
181     * "optimistic" seqlock-reader-style stamps. Because we must use
182     * a small finite number of bits (currently 7) for readers, a
183 jsr166 1.4 * supplementary reader overflow word is used when then number of
184 dl 1.1 * readers exceeds the count field. We do this by treating the max
185     * reader count value (RBITS) as a spinlock protecting overflow
186     * updates.
187     *
188     * Waiting readers and writers use different queues. The writer
189     * queue is a modified form of CLH lock. (For discussion of CLH,
190     * see the internal documentation of AbstractQueuedSynchronizer.)
191     * The reader "queue" is a form of Treiber stack, that supports
192     * simpler/faster operations because order within a queue doesn't
193     * matter and all are signalled at once. However the sequence of
194     * threads within the queue vs the current stamp does matter (see
195     * Shirako et al) so each carries its incoming stamp value.
196     * Waiting writers never need to track sequence values, so they
197     * don't.
198     *
199     * These queue mechanics hardwire the scheduling policy. Ignoring
200     * trylocks, cancellation, and spinning, they implement Phase-Fair
201     * preferences:
202     * 1. Unlocked writers prefer to signal waiting readers
203     * 2. Fully unlocked readers prefer to signal waiting writers
204     * 3. When read-locked and a waiting writer exists, the writer
205     * is preferred to incoming readers
206     *
207     * These rules apply to threads actually queued. All tryLock forms
208     * opportunistically try to acquire locks regardless of preference
209     * rules, and so may "barge" their way in. Additionally, initial
210     * phases of the await* methods (invoked from readLock() and
211     * writeLock()) use controlled spins that have similar effect.
212     * Phase-fair preferences may also be broken on cancellations due
213     * to timeouts and interrupts. Rule #3 (incoming readers when a
214     * waiting writer) is approximated with varying precision in
215     * different contexts -- some checks do not account for
216     * in-progress spins/signals, and others do not account for
217     * cancellations.
218     *
219     * As noted in Boehm's paper (above), sequence validation (mainly
220     * method validate()) requires stricter ordering rules than apply
221     * to normal volatile reads (of "state"). In the absence of (but
222     * continual hope for) explicit JVM support of intrinsics with
223     * double-sided reordering prohibition, or corresponding fence
224     * intrinsics, we for now uncomfortably rely on the fact that the
225     * Unsafe.getXVolatile intrinsic must have this property
226     * (syntactic volatile reads do not) for internal purposes anyway,
227     * even though it is not documented.
228     *
229     * The memory layout keeps lock state and queue pointers together
230     * (normally on the same cache line). This usually works well for
231     * read-mostly loads. In most other cases, the natural tendency of
232     * adaptive-spin CLH locks to reduce memory contention lessens
233     * motivation to further spread out contended locations, but might
234     * be subject to future improvements.
235     */
236    
237     /** Number of processors, for spin control */
238     private static final int NCPU = Runtime.getRuntime().availableProcessors();
239    
240     /** Maximum number of retries before blocking on acquisition */
241 jsr166 1.4 private static final int SPINS = (NCPU > 1) ? 1 << 6 : 1;
242 dl 1.1
243 dl 1.6 /** Maximum number of retries before re-blocking */
244 jsr166 1.4 private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 12 : 1;
245 dl 1.1
246     /** The period for yielding when waiting for overflow spinlock */
247     private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
248    
249     /** The number of bits to use for reader count before overflowing */
250     private static final int LG_READERS = 7;
251    
252     // Values for lock state and stamp operations
253     private static final long RUNIT = 1L;
254     private static final long WBIT = 1L << LG_READERS;
255     private static final long RBITS = WBIT - 1L;
256     private static final long RFULL = RBITS - 1L;
257     private static final long ABITS = RBITS | WBIT;
258     private static final long SBITS = ~RBITS; // note overlap with ABITS
259    
260     // Initial value for lock state; avoid failure value zero
261     private static final long ORIGIN = WBIT << 1;
262    
263     // Special value from cancelled await methods so caller can throw IE
264     private static final long INTERRUPTED = 1L;
265    
266     // Values for writer status; order matters
267     private static final int WAITING = -1;
268     private static final int CANCELLED = 1;
269    
270     /** Wait nodes for readers */
271     static final class RNode {
272     final long seq; // stamp value upon enqueue
273     volatile Thread waiter; // null if no longer waiting
274     volatile RNode next;
275     RNode(long s, Thread w) { seq = s; waiter = w; }
276     }
277    
278     /** Wait nodes for writers */
279     static final class WNode {
280     volatile int status; // 0, WAITING, or CANCELLED
281     volatile WNode prev;
282     volatile WNode next;
283     volatile Thread thread;
284     WNode(Thread t, WNode p) { thread = t; prev = p; }
285     }
286    
287     /** Head of writer CLH queue */
288     private transient volatile WNode whead;
289     /** Tail (last) of writer CLH queue */
290     private transient volatile WNode wtail;
291     /** Head of read queue */
292     private transient volatile RNode rhead;
293     /** The state of the lock -- high bits hold sequence, low bits read count */
294     private transient volatile long state;
295     /** extra reader count when state read count saturated */
296     private transient int readerOverflow;
297    
298     /**
299     * Creates a new lock initially in unlocked state.
300     */
301     public StampedLock() {
302     state = ORIGIN;
303     }
304    
305     /**
306     * Exclusively acquires the lock, blocking if necessary
307     * until available.
308     *
309 jsr166 1.4 * @return a stamp that can be used to unlock or convert mode
310 dl 1.1 */
311     public long writeLock() {
312     long s, next;
313     if (((s = state) & ABITS) == 0L &&
314     U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
315     return next;
316     return awaitWrite(false, 0L);
317     }
318    
319     /**
320     * Exclusively acquires the lock if it is immediately available.
321     *
322     * @return a stamp that can be used to unlock or convert mode,
323     * or zero if the lock is not available.
324     */
325     public long tryWriteLock() {
326     long s, next;
327     if (((s = state) & ABITS) == 0L &&
328     U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
329     return next;
330     return 0L;
331     }
332    
333     /**
334     * Exclusively acquires the lock if it is available within the
335 jsr166 1.5 * given time and the current thread has not been interrupted.
336 dl 1.1 *
337     * @return a stamp that can be used to unlock or convert mode,
338 jsr166 1.4 * or zero if the lock is not available
339 dl 1.1 * @throws InterruptedException if the current thread is interrupted
340 jsr166 1.4 * before acquiring the lock
341 dl 1.1 */
342     public long tryWriteLock(long time, TimeUnit unit)
343     throws InterruptedException {
344 jsr166 1.4 long nanos = unit.toNanos(time);
345 dl 1.1 if (!Thread.interrupted()) {
346     long s, next, deadline;
347     if (((s = state) & ABITS) == 0L &&
348     U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
349     return next;
350     if (nanos <= 0L)
351     return 0L;
352     if ((deadline = System.nanoTime() + nanos) == 0L)
353     deadline = 1L;
354     if ((next = awaitWrite(true, deadline)) != INTERRUPTED)
355     return next;
356     }
357     throw new InterruptedException();
358     }
359    
360     /**
361     * Exclusively acquires the lock, blocking if necessary
362     * until available or the current thread is interrupted.
363     *
364 jsr166 1.4 * @return a stamp that can be used to unlock or convert mode
365 dl 1.1 * @throws InterruptedException if the current thread is interrupted
366 jsr166 1.4 * before acquiring the lock
367 dl 1.1 */
368     public long writeLockInterruptibly() throws InterruptedException {
369     if (!Thread.interrupted()) {
370     long s, next;
371     if (((s = state) & ABITS) == 0L &&
372     U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
373     return next;
374     if ((next = awaitWrite(true, 0L)) != INTERRUPTED)
375     return next;
376     }
377     throw new InterruptedException();
378     }
379    
380     /**
381     * Non-exclusively acquires the lock, blocking if necessary
382     * until available.
383     *
384 jsr166 1.4 * @return a stamp that can be used to unlock or convert mode
385 dl 1.1 */
386     public long readLock() {
387     for (;;) {
388     long s, m, next;
389     if ((m = (s = state) & ABITS) == 0L ||
390     (m < WBIT && whead == wtail)) {
391     if (m < RFULL) {
392     if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
393     return next;
394     }
395     else if ((next = tryIncReaderOverflow(s)) != 0L)
396     return next;
397     }
398     else
399     return awaitRead(s, false, 0L);
400     }
401     }
402    
403     /**
404     * Non-exclusively acquires the lock if it is immediately available.
405     *
406     * @return a stamp that can be used to unlock or convert mode,
407 jsr166 1.4 * or zero if the lock is not available
408 dl 1.1 */
409     public long tryReadLock() {
410     for (;;) {
411     long s, m, next;
412     if ((m = (s = state) & ABITS) == WBIT)
413     return 0L;
414     else if (m < RFULL) {
415     if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
416     return next;
417     }
418     else if ((next = tryIncReaderOverflow(s)) != 0L)
419     return next;
420     }
421     }
422    
423     /**
424     * Non-exclusively acquires the lock if it is available within the
425 jsr166 1.5 * given time and the current thread has not been interrupted.
426 dl 1.1 *
427     * @return a stamp that can be used to unlock or convert mode,
428 jsr166 1.4 * or zero if the lock is not available
429 dl 1.1 * @throws InterruptedException if the current thread is interrupted
430 jsr166 1.4 * before acquiring the lock
431 dl 1.1 */
432     public long tryReadLock(long time, TimeUnit unit)
433     throws InterruptedException {
434     long nanos = unit.toNanos(time);
435     if (!Thread.interrupted()) {
436     for (;;) {
437     long s, m, next, deadline;
438     if ((m = (s = state) & ABITS) == WBIT ||
439     (m != 0L && whead != wtail)) {
440     if (nanos <= 0L)
441     return 0L;
442     if ((deadline = System.nanoTime() + nanos) == 0L)
443     deadline = 1L;
444     if ((next = awaitRead(s, true, deadline)) != INTERRUPTED)
445     return next;
446     break;
447     }
448     else if (m < RFULL) {
449     if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
450     return next;
451     }
452     else if ((next = tryIncReaderOverflow(s)) != 0L)
453     return next;
454     }
455     }
456     throw new InterruptedException();
457     }
458    
459     /**
460     * Non-exclusively acquires the lock, blocking if necessary
461     * until available or the current thread is interrupted.
462     *
463 jsr166 1.4 * @return a stamp that can be used to unlock or convert mode
464 dl 1.1 * @throws InterruptedException if the current thread is interrupted
465 jsr166 1.4 * before acquiring the lock
466 dl 1.1 */
467     public long readLockInterruptibly() throws InterruptedException {
468     if (!Thread.interrupted()) {
469     for (;;) {
470     long s, next, m;
471     if ((m = (s = state) & ABITS) == WBIT ||
472     (m != 0L && whead != wtail)) {
473     if ((next = awaitRead(s, true, 0L)) != INTERRUPTED)
474     return next;
475     break;
476     }
477     else if (m < RFULL) {
478     if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
479     return next;
480     }
481     else if ((next = tryIncReaderOverflow(s)) != 0L)
482     return next;
483     }
484     }
485     throw new InterruptedException();
486     }
487    
488     /**
489     * Returns a stamp that can later be validated, or zero
490     * if exclusively locked.
491     *
492     * @return a stamp, or zero if exclusively locked
493     */
494     public long tryOptimisticRead() {
495     long s;
496     return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
497     }
498    
499     /**
500     * Returns true if the lock has not been exclusively held since
501     * issuance of the given stamp. Always returns false if the stamp
502     * is zero. Always returns true if the stamp represents a
503     * currently held lock.
504     *
505     * @return true if the lock has not been exclusively held since
506     * issuance of the given stamp; else false
507     */
508     public boolean validate(long stamp) {
509     return (stamp & SBITS) == (U.getLongVolatile(this, STATE) & SBITS);
510     }
511    
512     /**
513     * If the lock state matches the given stamp, releases the
514     * exclusive lock.
515     *
516     * @param stamp a stamp returned by a write-lock operation
517     * @throws IllegalMonitorStateException if the stamp does
518 jsr166 1.4 * not match the current state of this lock
519 dl 1.1 */
520     public void unlockWrite(long stamp) {
521     if (state != stamp || (stamp & WBIT) == 0L)
522     throw new IllegalMonitorStateException();
523     state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
524     readerPrefSignal();
525     }
526    
527     /**
528     * If the lock state matches the given stamp, releases
529     * non-exclusive lock.
530     *
531     * @param stamp a stamp returned by a read-lock operation
532     * @throws IllegalMonitorStateException if the stamp does
533 jsr166 1.4 * not match the current state of this lock
534 dl 1.1 */
535     public void unlockRead(long stamp) {
536     long s, m;
537     if ((stamp & RBITS) != 0L) {
538     while (((s = state) & SBITS) == (stamp & SBITS)) {
539     if ((m = s & ABITS) == 0L)
540     break;
541     else if (m < RFULL) {
542     if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
543     if (m == RUNIT)
544     writerPrefSignal();
545     return;
546     }
547     }
548     else if (m >= WBIT)
549     break;
550     else if (tryDecReaderOverflow(s) != 0L)
551     return;
552     }
553     }
554     throw new IllegalMonitorStateException();
555     }
556    
557     /**
558     * If the lock state matches the given stamp, releases the
559     * corresponding mode of the lock.
560     *
561     * @param stamp a stamp returned by a lock operation
562     * @throws IllegalMonitorStateException if the stamp does
563 jsr166 1.4 * not match the current state of this lock
564 dl 1.1 */
565     public void unlock(long stamp) {
566     long a = stamp & ABITS, m, s;
567     while (((s = state) & SBITS) == (stamp & SBITS)) {
568     if ((m = s & ABITS) == 0L)
569     break;
570     else if (m == WBIT) {
571     if (a != m)
572     break;
573     state = (s += WBIT) == 0L ? ORIGIN : s;
574     readerPrefSignal();
575     return;
576     }
577     else if (a == 0L || a >= WBIT)
578     break;
579     else if (m < RFULL) {
580     if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
581     if (m == RUNIT)
582     writerPrefSignal();
583     return;
584     }
585     }
586     else if (tryDecReaderOverflow(s) != 0L)
587     return;
588     }
589     throw new IllegalMonitorStateException();
590     }
591    
592     /**
593     * If the lock state matches the given stamp then performs one of
594     * the following actions. If the stamp represents holding a write
595     * lock, returns it. Or, if a read lock, if the write lock is
596     * available, releases the read and returns a write stamp. Or, if
597     * an optimistic read, returns a write stamp only if immediately
598     * available. This method returns zero in all other cases.
599     *
600     * @param stamp a stamp
601     * @return a valid write stamp, or zero on failure
602     */
603     public long tryConvertToWriteLock(long stamp) {
604     long a = stamp & ABITS, m, s, next;
605     while (((s = state) & SBITS) == (stamp & SBITS)) {
606     if ((m = s & ABITS) == 0L) {
607     if (a != 0L)
608     break;
609     if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
610     return next;
611     }
612     else if (m == WBIT) {
613     if (a != m)
614     break;
615     return stamp;
616     }
617     else if (m == RUNIT && a != 0L && a < WBIT) {
618     if (U.compareAndSwapLong(this, STATE, s,
619     next = s - RUNIT + WBIT))
620     return next;
621     }
622     else
623     break;
624     }
625     return 0L;
626     }
627    
628     /**
629     * If the lock state matches the given stamp then performs one of
630     * the following actions. If the stamp represents holding a write
631     * lock, releases it and obtains a read lock. Or, if a read lock,
632     * returns it. Or, if an optimistic read, acquires a read lock and
633     * returns a read stamp only if immediately available. This method
634     * returns zero in all other cases.
635     *
636     * @param stamp a stamp
637     * @return a valid read stamp, or zero on failure
638     */
639     public long tryConvertToReadLock(long stamp) {
640     long a = stamp & ABITS, m, s, next;
641     while (((s = state) & SBITS) == (stamp & SBITS)) {
642     if ((m = s & ABITS) == 0L) {
643     if (a != 0L)
644     break;
645     else if (m < RFULL) {
646     if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
647     return next;
648     }
649     else if ((next = tryIncReaderOverflow(s)) != 0L)
650     return next;
651     }
652     else if (m == WBIT) {
653     if (a != m)
654     break;
655     next = state = s + (WBIT + RUNIT);
656     readerPrefSignal();
657     return next;
658     }
659     else if (a != 0L && a < WBIT)
660     return stamp;
661     else
662     break;
663     }
664     return 0L;
665     }
666    
667     /**
668     * If the lock state matches the given stamp then, if the stamp
669     * represents holding a lock, releases it and returns an
670     * observation stamp. Or, if an optimistic read, returns it if
671     * validated. This method returns zero in all other cases, and so
672     * may be useful as a form of "tryUnlock".
673     *
674     * @param stamp a stamp
675     * @return a valid optimistic read stamp, or zero on failure
676     */
677     public long tryConvertToOptimisticRead(long stamp) {
678     long a = stamp & ABITS, m, s, next;
679 jsr166 1.2 while (((s = U.getLongVolatile(this, STATE)) &
680 dl 1.1 SBITS) == (stamp & SBITS)) {
681     if ((m = s & ABITS) == 0L) {
682     if (a != 0L)
683     break;
684     return s;
685     }
686     else if (m == WBIT) {
687     if (a != m)
688     break;
689     next = state = (s += WBIT) == 0L ? ORIGIN : s;
690     readerPrefSignal();
691     return next;
692     }
693     else if (a == 0L || a >= WBIT)
694     break;
695     else if (m < RFULL) {
696     if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
697     if (m == RUNIT)
698     writerPrefSignal();
699     return next & SBITS;
700     }
701     }
702     else if ((next = tryDecReaderOverflow(s)) != 0L)
703     return next & SBITS;
704     }
705     return 0L;
706     }
707    
708     /**
709     * Releases the write lock if it is held, without requiring a
710     * stamp value. This method may be useful for recovery after
711     * errors.
712     *
713 jsr166 1.4 * @return true if the lock was held, else false
714 dl 1.1 */
715     public boolean tryUnlockWrite() {
716     long s;
717     if (((s = state) & WBIT) != 0L) {
718     state = (s += WBIT) == 0L ? ORIGIN : s;
719     readerPrefSignal();
720     return true;
721     }
722     return false;
723     }
724    
725     /**
726     * Releases one hold of the read lock if it is held, without
727     * requiring a stamp value. This method may be useful for recovery
728     * after errors.
729     *
730 jsr166 1.4 * @return true if the read lock was held, else false
731 dl 1.1 */
732     public boolean tryUnlockRead() {
733     long s, m;
734     while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
735     if (m < RFULL) {
736     if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
737     if (m == RUNIT)
738     writerPrefSignal();
739     return true;
740     }
741     }
742     else if (tryDecReaderOverflow(s) != 0L)
743     return true;
744     }
745     return false;
746     }
747    
748     /**
749     * Returns true if the lock is currently held exclusively.
750     *
751     * @return true if the lock is currently held exclusively
752     */
753     public boolean isWriteLocked() {
754     return (state & WBIT) != 0L;
755     }
756    
757     /**
758     * Returns true if the lock is currently held non-exclusively.
759     *
760     * @return true if the lock is currently held non-exclusively
761     */
762     public boolean isReadLocked() {
763     long m;
764     return (m = state & ABITS) > 0L && m < WBIT;
765     }
766    
767     private void readObject(java.io.ObjectInputStream s)
768     throws java.io.IOException, ClassNotFoundException {
769     s.defaultReadObject();
770     state = ORIGIN; // reset to unlocked state
771     }
772    
773     // internals
774    
775     /**
776     * Tries to increment readerOverflow by first setting state
777     * access bits value to RBITS, indicating hold of spinlock,
778     * then updating, then releasing.
779 jsr166 1.4 *
780 dl 1.1 * @param stamp, assumed that (stamp & ABITS) >= RFULL
781     * @return new stamp on success, else zero
782     */
783     private long tryIncReaderOverflow(long s) {
784     if ((s & ABITS) == RFULL) {
785     if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
786     ++readerOverflow;
787     state = s;
788     return s;
789     }
790     }
791 jsr166 1.2 else if ((ThreadLocalRandom.current().nextInt() &
792 dl 1.1 OVERFLOW_YIELD_RATE) == 0)
793     Thread.yield();
794     return 0L;
795     }
796    
797     /**
798     * Tries to decrement readerOverflow.
799 jsr166 1.4 *
800 dl 1.1 * @param stamp, assumed that (stamp & ABITS) >= RFULL
801     * @return new stamp on success, else zero
802     */
803     private long tryDecReaderOverflow(long s) {
804     if ((s & ABITS) == RFULL) {
805     if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
806     int r; long next;
807     if ((r = readerOverflow) > 0) {
808     readerOverflow = r - 1;
809     next = s;
810     }
811     else
812     next = s - RUNIT;
813     state = next;
814     return next;
815     }
816     }
817 jsr166 1.2 else if ((ThreadLocalRandom.current().nextInt() &
818 dl 1.1 OVERFLOW_YIELD_RATE) == 0)
819     Thread.yield();
820     return 0L;
821     }
822    
823     /*
824     * The two versions of signal implement the phase-fair policy.
825     * They include almost the same code, but repacked in different
826     * ways. Integrating the policy with the mechanics eliminates
827     * state rechecks that would be needed with separate reader and
828     * writer signal methods. Both methods assume that they are
829     * called when the lock is last known to be available, and
830     * continue until the lock is unavailable, or at least one thread
831     * is signalled, or there are no more waiting threads. Signalling
832     * a reader entails popping (CASing) from rhead and unparking
833     * unless the thread already cancelled (indicated by a null waiter
834     * field). Signalling a writer requires finding the first node,
835     * i.e., the successor of whead. This is normally just head.next,
836     * but may require traversal from wtail if next pointers are
837     * lagging. These methods may fail to wake up an acquiring thread
838     * when one or more have been cancelled, but the cancel methods
839     * themselves provide extra safeguards to ensure liveness.
840     */
841    
842     private void readerPrefSignal() {
843     boolean readers = false;
844     RNode p; WNode h, q; long s; Thread w;
845     while ((p = rhead) != null) {
846     if (((s = state) & WBIT) != 0L)
847     return;
848     if (p.seq == (s & SBITS))
849     break;
850     readers = true;
851     if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
852     (w = p.waiter) != null &&
853     U.compareAndSwapObject(p, WAITER, w, null))
854     U.unpark(w);
855     }
856     if (!readers && (state & ABITS) == 0L &&
857     (h = whead) != null && h.status != 0) {
858     U.compareAndSwapInt(h, STATUS, WAITING, 0);
859     if ((q = h.next) == null || q.status == CANCELLED) {
860     q = null;
861     for (WNode t = wtail; t != null && t != h; t = t.prev)
862     if (t.status <= 0)
863     q = t;
864     }
865     if (q != null && (w = q.thread) != null)
866     U.unpark(w);
867     }
868     }
869    
870     private void writerPrefSignal() {
871     RNode p; WNode h, q; long s; Thread w;
872     if ((h = whead) != null && h.status != 0) {
873     U.compareAndSwapInt(h, STATUS, WAITING, 0);
874     if ((q = h.next) == null || q.status == CANCELLED) {
875     q = null;
876     for (WNode t = wtail; t != null && t != h; t = t.prev)
877     if (t.status <= 0)
878     q = t;
879     }
880     if (q != null && (w = q.thread) != null)
881     U.unpark(w);
882     }
883     else {
884     while ((p = rhead) != null && ((s = state) & WBIT) == 0L &&
885     p.seq != (s & SBITS)) {
886     if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
887     (w = p.waiter) != null &&
888     U.compareAndSwapObject(p, WAITER, w, null))
889     U.unpark(w);
890     }
891     }
892     }
893    
894     /**
895     * RNG for local spins. The first call from await{Read,Write}
896     * produces a thread-local value. Unless zero, subsequent calls
897     * use an xorShift to further reduce memory traffic. Both await
898     * methods use a similar spin strategy: If associated queue
899     * appears to be empty, then the thread spin-waits up to SPINS
900     * times before enqueing, and then, if the first thread to be
901     * enqueued, spins again up to SPINS times before blocking. If,
902     * upon wakening it fails to obtain lock, and is still (or
903     * becomes) the first waiting thread (which indicates that some
904     * other thread barged and obtained lock), it escalates spins (up
905     * to MAX_HEAD_SPINS) to reduce the likelihood of continually
906     * losing to barging threads.
907     */
908     private static int nextRandom(int r) {
909     if (r == 0)
910     return ThreadLocalRandom.current().nextInt();
911     r ^= r << 1; // xorshift
912     r ^= r >>> 3;
913     r ^= r << 10;
914     return r;
915     }
916    
917     /**
918     * Possibly spins trying to obtain write lock, then enqueues and
919 jsr166 1.4 * blocks while not head of write queue or cannot acquire lock,
920 dl 1.1 * possibly spinning when at head; cancelling on timeout or
921     * interrupt.
922     *
923     * @param interruptible true if should check interrupts and if so
924     * return INTERRUPTED
925     * @param deadline if nonzero, the System.nanoTime value to timeout
926 jsr166 1.4 * at (and return zero)
927 dl 1.1 */
928     private long awaitWrite(boolean interruptible, long deadline) {
929     WNode node = null;
930     for (int r = 0, spins = -1;;) {
931     WNode p; long s, next;
932     if (((s = state) & ABITS) == 0L) {
933     if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
934     return next;
935     }
936     else if (spins < 0)
937     spins = whead == wtail ? SPINS : 0;
938     else if (spins > 0) {
939     if ((r = nextRandom(r)) >= 0)
940     --spins;
941     }
942     else if ((p = wtail) == null) { // initialize queue
943     if (U.compareAndSwapObject(this, WHEAD, null,
944     new WNode(null, null)))
945     wtail = whead;
946     }
947     else if (node == null)
948     node = new WNode(Thread.currentThread(), p);
949     else if (node.prev != p)
950     node.prev = p;
951     else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
952     p.next = node;
953     for (int headSpins = SPINS;;) {
954     WNode np; int ps;
955     if ((np = node.prev) != p && np != null)
956     (p = np).next = node; // stale
957     if (p == whead) {
958     for (int k = headSpins;;) {
959     if (((s = state) & ABITS) == 0L) {
960     if (U.compareAndSwapLong(this, STATE,
961     s, next = s + WBIT)) {
962     whead = node;
963     node.thread = null;
964     node.prev = null;
965     return next;
966     }
967     break;
968     }
969     if ((r = nextRandom(r)) >= 0 && --k <= 0)
970     break;
971     }
972     if (headSpins < MAX_HEAD_SPINS)
973     headSpins <<= 1;
974     }
975     if ((ps = p.status) == 0)
976     U.compareAndSwapInt(p, STATUS, 0, WAITING);
977     else if (ps == CANCELLED)
978     node.prev = p.prev;
979     else {
980     long time; // 0 argument to park means no timeout
981     if (deadline == 0L)
982     time = 0L;
983     else if ((time = deadline - System.nanoTime()) <= 0L)
984     return cancelWriter(node, false);
985     if (node.prev == p && p.status == WAITING &&
986     (p != whead || (state & WBIT) != 0L)) { // recheck
987     U.park(false, time);
988     if (interruptible && Thread.interrupted())
989     return cancelWriter(node, true);
990     }
991     }
992     }
993     }
994     }
995     }
996    
997     /**
998     * If node non-null, forces cancel status and unsplices from queue
999     * if possible. This is a streamlined variant of cancellation
1000     * methods in AbstractQueuedSynchronizer that includes a detailed
1001     * explanation.
1002     */
1003     private long cancelWriter(WNode node, boolean interrupted) {
1004     WNode pred;
1005     if (node != null && (pred = node.prev) != null) {
1006     WNode pp;
1007     node.thread = null;
1008     while (pred.status == CANCELLED && (pp = pred.prev) != null)
1009     pred = node.prev = pp;
1010     WNode predNext = pred.next;
1011     node.status = CANCELLED;
1012     if (predNext != null) {
1013     Thread w = null;
1014     WNode succ = node.next;
1015     while (succ != null && succ.status == CANCELLED)
1016     succ = succ.next;
1017     if (succ != null)
1018     w = succ.thread;
1019     else if (node == wtail)
1020     U.compareAndSwapObject(this, WTAIL, node, pred);
1021     U.compareAndSwapObject(pred, WNEXT, predNext, succ);
1022     if (w != null)
1023     U.unpark(w);
1024     }
1025     }
1026     writerPrefSignal();
1027 jsr166 1.3 return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1028 dl 1.1 }
1029    
1030 jsr166 1.4 /**
1031 dl 1.1 * Waits for read lock or timeout or interrupt. The form of
1032     * awaitRead differs from awaitWrite mainly because it must
1033     * restart (with a new wait node) if the thread was unqueued and
1034     * unparked but could not the obtain lock. We also need to help
1035     * with preference rules by not trying to acquire the lock before
1036     * enqueuing if there is a known waiting writer, but also helping
1037     * to release those threads that are still queued from the last
1038     * release.
1039     */
1040     private long awaitRead(long stamp, boolean interruptible, long deadline) {
1041     long seq = stamp & SBITS;
1042     RNode node = null;
1043     boolean queued = false;
1044     for (int r = 0, headSpins = SPINS, spins = -1;;) {
1045     long s, m, next; RNode p; WNode wh; Thread w;
1046     if ((m = (s = state) & ABITS) != WBIT &&
1047     ((s & SBITS) != seq || (wh = whead) == null ||
1048     wh.status == 0)) {
1049     if (m < RFULL ?
1050     U.compareAndSwapLong(this, STATE, s, next = s + RUNIT) :
1051     (next = tryIncReaderOverflow(s)) != 0L) {
1052     if (node != null && (w = node.waiter) != null)
1053     U.compareAndSwapObject(node, WAITER, w, null);
1054     if ((p = rhead) != null && (s & SBITS) != p.seq &&
1055     U.compareAndSwapObject(this, RHEAD, p, p.next) &&
1056     (w = p.waiter) != null &&
1057     U.compareAndSwapObject(p, WAITER, w, null))
1058     U.unpark(w); // help signal other waiters
1059     return next;
1060     }
1061     }
1062     else if (m != WBIT && (p = rhead) != null &&
1063     (s & SBITS) != p.seq) { // help release old readers
1064     if (U.compareAndSwapObject(this, RHEAD, p, p.next) &&
1065     (w = p.waiter) != null &&
1066     U.compareAndSwapObject(p, WAITER, w, null))
1067     U.unpark(w);
1068     }
1069     else if (queued && node != null && node.waiter == null) {
1070     node = null; // restart
1071     queued = false;
1072     spins = -1;
1073     }
1074     else if (spins < 0) {
1075     if (rhead != node)
1076     spins = 0;
1077     else if ((spins = headSpins) < MAX_HEAD_SPINS && node != null)
1078     headSpins <<= 1;
1079     }
1080     else if (spins > 0) {
1081     if ((r = nextRandom(r)) >= 0)
1082     --spins;
1083     }
1084     else if (node == null)
1085     node = new RNode(seq, Thread.currentThread());
1086     else if (!queued) {
1087     if (queued = U.compareAndSwapObject(this, RHEAD,
1088     node.next = rhead, node))
1089     spins = -1;
1090     }
1091     else {
1092     long time;
1093     if (deadline == 0L)
1094     time = 0L;
1095     else if ((time = deadline - System.nanoTime()) <= 0L)
1096     return cancelReader(node, false);
1097     if ((state & WBIT) != 0L && node.waiter != null) { // recheck
1098     U.park(false, time);
1099     if (interruptible && Thread.interrupted())
1100     return cancelReader(node, true);
1101     }
1102     }
1103     }
1104     }
1105    
1106     /**
1107     * If node non-null, forces cancel status and unsplices from queue
1108     * if possible, by traversing entire queue looking for cancelled
1109 dl 1.6 * nodes.
1110 dl 1.1 */
1111     private long cancelReader(RNode node, boolean interrupted) {
1112     Thread w;
1113     if (node != null && (w = node.waiter) != null &&
1114     U.compareAndSwapObject(node, WAITER, w, null)) {
1115     for (RNode pred = null, p = rhead; p != null;) {
1116     RNode q = p.next;
1117     if (p.waiter == null) {
1118     if (pred == null) {
1119     U.compareAndSwapObject(this, RHEAD, p, q);
1120     p = rhead;
1121     }
1122     else {
1123     U.compareAndSwapObject(pred, RNEXT, p, q);
1124 dl 1.6 p = pred.next;
1125 dl 1.1 }
1126     }
1127     else {
1128     pred = p;
1129     p = q;
1130     }
1131     }
1132     }
1133     readerPrefSignal();
1134 jsr166 1.3 return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1135 dl 1.1 }
1136    
1137     // Unsafe mechanics
1138     private static final sun.misc.Unsafe U;
1139     private static final long STATE;
1140     private static final long RHEAD;
1141     private static final long WHEAD;
1142     private static final long WTAIL;
1143     private static final long RNEXT;
1144     private static final long WNEXT;
1145     private static final long WPREV;
1146     private static final long WAITER;
1147     private static final long STATUS;
1148    
1149     static {
1150     try {
1151     U = getUnsafe();
1152     Class<?> k = StampedLock.class;
1153     Class<?> rk = RNode.class;
1154     Class<?> wk = WNode.class;
1155     STATE = U.objectFieldOffset
1156     (k.getDeclaredField("state"));
1157     RHEAD = U.objectFieldOffset
1158     (k.getDeclaredField("rhead"));
1159     WHEAD = U.objectFieldOffset
1160     (k.getDeclaredField("whead"));
1161     WTAIL = U.objectFieldOffset
1162     (k.getDeclaredField("wtail"));
1163     RNEXT = U.objectFieldOffset
1164     (rk.getDeclaredField("next"));
1165     WAITER = U.objectFieldOffset
1166     (rk.getDeclaredField("waiter"));
1167     STATUS = U.objectFieldOffset
1168     (wk.getDeclaredField("status"));
1169     WNEXT = U.objectFieldOffset
1170     (wk.getDeclaredField("next"));
1171     WPREV = U.objectFieldOffset
1172     (wk.getDeclaredField("prev"));
1173    
1174     } catch (Exception e) {
1175     throw new Error(e);
1176     }
1177     }
1178    
1179     /**
1180     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
1181     * Replace with a simple call to Unsafe.getUnsafe when integrating
1182     * into a jdk.
1183     *
1184     * @return a sun.misc.Unsafe
1185     */
1186     private static sun.misc.Unsafe getUnsafe() {
1187     try {
1188     return sun.misc.Unsafe.getUnsafe();
1189     } catch (SecurityException se) {
1190     try {
1191     return java.security.AccessController.doPrivileged
1192     (new java.security
1193     .PrivilegedExceptionAction<sun.misc.Unsafe>() {
1194     public sun.misc.Unsafe run() throws Exception {
1195     java.lang.reflect.Field f = sun.misc
1196     .Unsafe.class.getDeclaredField("theUnsafe");
1197     f.setAccessible(true);
1198     return (sun.misc.Unsafe) f.get(null);
1199     }});
1200     } catch (java.security.PrivilegedActionException e) {
1201     throw new RuntimeException("Could not initialize intrinsics",
1202     e.getCause());
1203     }
1204     }
1205     }
1206    
1207     }