ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
Revision: 1.27
Committed: Mon Jan 14 19:00:01 2013 UTC (11 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.26: +2 -0 lines
Log Message:
add serialVersionUID to fix javac [serial] warning

File Contents

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