ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/jsr166e/StampedLock.java
Revision: 1.39
Committed: Sun Jan 18 20:17:33 2015 UTC (9 years, 4 months ago) by jsr166
Branch: MAIN
Changes since 1.38: +1 -0 lines
Log Message:
exactly one blank line before and after package statements

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.TimeUnit;
10 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
15 /**
16 * A capability-based lock with three modes for controlling read/write
17 * access. The state of a StampedLock consists of a version and mode.
18 * Lock acquisition methods return a stamp that represents and
19 * 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 * and all optimistic read validations will fail. </li>
33 *
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 * 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 *
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 * a valid write stamp if (1) already in writing mode (2) in reading
63 * 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 * <p>StampedLocks are designed for use as internal utilities in the
69 * development of thread-safe components. Their use relies on
70 * knowledge of the internal properties of the data, objects, and
71 * 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 * 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 * <p>The scheduling policy of StampedLock does not consistently
87 * 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 *
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 * private double x, y;
109 * 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 * 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 * }
133 * return Math.sqrt(currentX * currentX + currentY * currentY);
134 * }
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 * long ws = sl.tryConvertToWriteLock(stamp);
142 * 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 * sl.unlock(stamp);
155 * }
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 * and Ordered RW locks (see Shirako et al
172 * 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 * supplementary reader overflow word is used when the number of
181 * 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 * Waiters use a modified form of CLH lock used in
186 * AbstractQueuedSynchronizer (see its internal documentation for
187 * a fuller account), where each node is tagged (field mode) as
188 * 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 * 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 * 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.) Method release
201 * does not (and sometimes cannot) itself wake up cowaiters. This
202 * is done by the primary thread, but helped by any other threads
203 * with nothing better to do in methods acquireRead and
204 * acquireWrite.
205 *
206 * These rules apply to threads actually queued. All tryLock forms
207 * opportunistically try to acquire locks regardless of preference
208 * rules, and so may "barge" their way in. Randomized spinning is
209 * used in the acquire methods to reduce (increasingly expensive)
210 * context switching while also avoiding sustained memory
211 * thrashing among many threads. We limit spins to the head of
212 * queue. A thread spin-waits up to SPINS times (where each
213 * iteration decreases spin count with 50% probability) before
214 * blocking. If, upon wakening it fails to obtain lock, and is
215 * still (or becomes) the first waiting thread (which indicates
216 * that some other thread barged and obtained lock), it escalates
217 * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
218 * continually losing to barging threads.
219 *
220 * Nearly all of these mechanics are carried out in methods
221 * acquireWrite and acquireRead, that, as typical of such code,
222 * sprawl out because actions and retries rely on consistent sets
223 * of locally cached reads.
224 *
225 * As noted in Boehm's paper (above), sequence validation (mainly
226 * method validate()) requires stricter ordering rules than apply
227 * to normal volatile reads (of "state"). In the absence of (but
228 * continual hope for) explicit JVM support of intrinsics with
229 * double-sided reordering prohibition, or corresponding fence
230 * intrinsics, we for now uncomfortably rely on the fact that the
231 * Unsafe.getXVolatile intrinsic must have this property
232 * (syntactic volatile reads do not) for internal purposes anyway,
233 * even though it is not documented.
234 *
235 * The memory layout keeps lock state and queue pointers together
236 * (normally on the same cache line). This usually works well for
237 * read-mostly loads. In most other cases, the natural tendency of
238 * adaptive-spin CLH locks to reduce memory contention lessens
239 * motivation to further spread out contended locations, but might
240 * be subject to future improvements.
241 */
242
243 private static final long serialVersionUID = -6001602636862214147L;
244
245 /** Number of processors, for spin control */
246 private static final int NCPU = Runtime.getRuntime().availableProcessors();
247
248 /** Maximum number of retries before enqueuing on acquisition */
249 private static final int SPINS = (NCPU > 1) ? 1 << 6 : 0;
250
251 /** Maximum number of retries before blocking at head on acquisition */
252 private static final int HEAD_SPINS = (NCPU > 1) ? 1 << 10 : 0;
253
254 /** Maximum number of retries before re-blocking */
255 private static final int MAX_HEAD_SPINS = (NCPU > 1) ? 1 << 16 : 0;
256
257 /** The period for yielding when waiting for overflow spinlock */
258 private static final int OVERFLOW_YIELD_RATE = 7; // must be power 2 - 1
259
260 /** The number of bits to use for reader count before overflowing */
261 private static final int LG_READERS = 7;
262
263 // Values for lock state and stamp operations
264 private static final long RUNIT = 1L;
265 private static final long WBIT = 1L << LG_READERS;
266 private static final long RBITS = WBIT - 1L;
267 private static final long RFULL = RBITS - 1L;
268 private static final long ABITS = RBITS | WBIT;
269 private static final long SBITS = ~RBITS; // note overlap with ABITS
270
271 // Initial value for lock state; avoid failure value zero
272 private static final long ORIGIN = WBIT << 1;
273
274 // Special value from cancelled acquire methods so caller can throw IE
275 private static final long INTERRUPTED = 1L;
276
277 // Values for node status; order matters
278 private static final int WAITING = -1;
279 private static final int CANCELLED = 1;
280
281 // Modes for nodes (int not boolean to allow arithmetic)
282 private static final int RMODE = 0;
283 private static final int WMODE = 1;
284
285 /** Wait nodes */
286 static final class WNode {
287 volatile WNode prev;
288 volatile WNode next;
289 volatile WNode cowait; // list of linked readers
290 volatile Thread thread; // non-null while possibly parked
291 volatile int status; // 0, WAITING, or CANCELLED
292 final int mode; // RMODE or WMODE
293 WNode(int m, WNode p) { mode = m; prev = p; }
294 }
295
296 /** Head of CLH queue */
297 private transient volatile WNode whead;
298 /** Tail (last) of CLH queue */
299 private transient volatile WNode wtail;
300
301 // views
302 transient ReadLockView readLockView;
303 transient WriteLockView writeLockView;
304 transient ReadWriteLockView readWriteLockView;
305
306 /** Lock sequence/state */
307 private transient volatile long state;
308 /** extra reader count when state read count saturated */
309 private transient int readerOverflow;
310
311 /**
312 * Creates a new lock, initially in unlocked state.
313 */
314 public StampedLock() {
315 state = ORIGIN;
316 }
317
318 /**
319 * Exclusively acquires the lock, blocking if necessary
320 * until available.
321 *
322 * @return a stamp that can be used to unlock or convert mode
323 */
324 public long writeLock() {
325 long s, next; // bypass acquireWrite in fully unlocked case only
326 return ((((s = state) & ABITS) == 0L &&
327 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
328 next : acquireWrite(false, 0L));
329 }
330
331 /**
332 * Exclusively acquires the lock if it is immediately available.
333 *
334 * @return a stamp that can be used to unlock or convert mode,
335 * or zero if the lock is not available
336 */
337 public long tryWriteLock() {
338 long s, next;
339 return ((((s = state) & ABITS) == 0L &&
340 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
341 next : 0L);
342 }
343
344 /**
345 * Exclusively acquires the lock if it is available within the
346 * given time and the current thread has not been interrupted.
347 * Behavior under timeout and interruption matches that specified
348 * for method {@link Lock#tryLock(long,TimeUnit)}.
349 *
350 * @param time the maximum time to wait for the lock
351 * @param unit the time unit of the {@code time} argument
352 * @return a stamp that can be used to unlock or convert mode,
353 * or zero if the lock is not available
354 * @throws InterruptedException if the current thread is interrupted
355 * before acquiring the lock
356 */
357 public long tryWriteLock(long time, TimeUnit unit)
358 throws InterruptedException {
359 long nanos = unit.toNanos(time);
360 if (!Thread.interrupted()) {
361 long next, deadline;
362 if ((next = tryWriteLock()) != 0L)
363 return next;
364 if (nanos <= 0L)
365 return 0L;
366 if ((deadline = System.nanoTime() + nanos) == 0L)
367 deadline = 1L;
368 if ((next = acquireWrite(true, deadline)) != INTERRUPTED)
369 return next;
370 }
371 throw new InterruptedException();
372 }
373
374 /**
375 * Exclusively acquires the lock, blocking if necessary
376 * until available or the current thread is interrupted.
377 * Behavior under interruption matches that specified
378 * for method {@link Lock#lockInterruptibly()}.
379 *
380 * @return a stamp that can be used to unlock or convert mode
381 * @throws InterruptedException if the current thread is interrupted
382 * before acquiring the lock
383 */
384 public long writeLockInterruptibly() throws InterruptedException {
385 long next;
386 if (!Thread.interrupted() &&
387 (next = acquireWrite(true, 0L)) != INTERRUPTED)
388 return next;
389 throw new InterruptedException();
390 }
391
392 /**
393 * Non-exclusively acquires the lock, blocking if necessary
394 * until available.
395 *
396 * @return a stamp that can be used to unlock or convert mode
397 */
398 public long readLock() {
399 long s = state, next; // bypass acquireRead on common uncontended case
400 return ((whead == wtail && (s & ABITS) < RFULL &&
401 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
402 next : acquireRead(false, 0L));
403 }
404
405 /**
406 * Non-exclusively acquires the lock if it is immediately available.
407 *
408 * @return a stamp that can be used to unlock or convert mode,
409 * or zero if the lock is not available
410 */
411 public long tryReadLock() {
412 for (;;) {
413 long s, m, next;
414 if ((m = (s = state) & ABITS) == WBIT)
415 return 0L;
416 else if (m < RFULL) {
417 if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
418 return next;
419 }
420 else if ((next = tryIncReaderOverflow(s)) != 0L)
421 return next;
422 }
423 }
424
425 /**
426 * Non-exclusively acquires the lock if it is available within the
427 * given time and the current thread has not been interrupted.
428 * Behavior under timeout and interruption matches that specified
429 * for method {@link Lock#tryLock(long,TimeUnit)}.
430 *
431 * @param time the maximum time to wait for the lock
432 * @param unit the time unit of the {@code time} argument
433 * @return a stamp that can be used to unlock or convert mode,
434 * or zero if the lock is not available
435 * @throws InterruptedException if the current thread is interrupted
436 * before acquiring the lock
437 */
438 public long tryReadLock(long time, TimeUnit unit)
439 throws InterruptedException {
440 long s, m, next, deadline;
441 long nanos = unit.toNanos(time);
442 if (!Thread.interrupted()) {
443 if ((m = (s = state) & ABITS) != WBIT) {
444 if (m < RFULL) {
445 if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
446 return next;
447 }
448 else if ((next = tryIncReaderOverflow(s)) != 0L)
449 return next;
450 }
451 if (nanos <= 0L)
452 return 0L;
453 if ((deadline = System.nanoTime() + nanos) == 0L)
454 deadline = 1L;
455 if ((next = acquireRead(true, deadline)) != INTERRUPTED)
456 return next;
457 }
458 throw new InterruptedException();
459 }
460
461 /**
462 * Non-exclusively acquires the lock, blocking if necessary
463 * until available or the current thread is interrupted.
464 * Behavior under interruption matches that specified
465 * for method {@link Lock#lockInterruptibly()}.
466 *
467 * @return a stamp that can be used to unlock or convert mode
468 * @throws InterruptedException if the current thread is interrupted
469 * before acquiring the lock
470 */
471 public long readLockInterruptibly() throws InterruptedException {
472 long next;
473 if (!Thread.interrupted() &&
474 (next = acquireRead(true, 0L)) != INTERRUPTED)
475 return next;
476 throw new InterruptedException();
477 }
478
479 /**
480 * Returns a stamp that can later be validated, or zero
481 * if exclusively locked.
482 *
483 * @return a stamp, or zero if exclusively locked
484 */
485 public long tryOptimisticRead() {
486 long s;
487 return (((s = state) & WBIT) == 0L) ? (s & SBITS) : 0L;
488 }
489
490 /**
491 * Returns true if the lock has not been exclusively acquired
492 * since issuance of the given stamp. Always returns false if the
493 * stamp is zero. Always returns true if the stamp represents a
494 * currently held lock. Invoking this method with a value not
495 * obtained from {@link #tryOptimisticRead} or a locking method
496 * for this lock has no defined effect or result.
497 *
498 * @param stamp a stamp
499 * @return {@code true} if the lock has not been exclusively acquired
500 * since issuance of the given stamp; else false
501 */
502 public boolean validate(long stamp) {
503 // See above about current use of getLongVolatile here
504 return (stamp & SBITS) == (U.getLongVolatile(this, STATE) & SBITS);
505 }
506
507 /**
508 * If the lock state matches the given stamp, releases the
509 * exclusive lock.
510 *
511 * @param stamp a stamp returned by a write-lock operation
512 * @throws IllegalMonitorStateException if the stamp does
513 * not match the current state of this lock
514 */
515 public void unlockWrite(long stamp) {
516 WNode h;
517 if (state != stamp || (stamp & WBIT) == 0L)
518 throw new IllegalMonitorStateException();
519 state = (stamp += WBIT) == 0L ? ORIGIN : stamp;
520 if ((h = whead) != null && h.status != 0)
521 release(h);
522 }
523
524 /**
525 * If the lock state matches the given stamp, releases the
526 * non-exclusive lock.
527 *
528 * @param stamp a stamp returned by a read-lock operation
529 * @throws IllegalMonitorStateException if the stamp does
530 * not match the current state of this lock
531 */
532 public void unlockRead(long stamp) {
533 long s, m; WNode h;
534 for (;;) {
535 if (((s = state) & SBITS) != (stamp & SBITS) ||
536 (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
537 throw new IllegalMonitorStateException();
538 if (m < RFULL) {
539 if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
540 if (m == RUNIT && (h = whead) != null && h.status != 0)
541 release(h);
542 break;
543 }
544 }
545 else if (tryDecReaderOverflow(s) != 0L)
546 break;
547 }
548 }
549
550 /**
551 * If the lock state matches the given stamp, releases the
552 * corresponding mode of the lock.
553 *
554 * @param stamp a stamp returned by a lock operation
555 * @throws IllegalMonitorStateException if the stamp does
556 * not match the current state of this lock
557 */
558 public void unlock(long stamp) {
559 long a = stamp & ABITS, m, s; WNode h;
560 while (((s = state) & SBITS) == (stamp & SBITS)) {
561 if ((m = s & ABITS) == 0L)
562 break;
563 else if (m == WBIT) {
564 if (a != m)
565 break;
566 state = (s += WBIT) == 0L ? ORIGIN : s;
567 if ((h = whead) != null && h.status != 0)
568 release(h);
569 return;
570 }
571 else if (a == 0L || a >= WBIT)
572 break;
573 else if (m < RFULL) {
574 if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
575 if (m == RUNIT && (h = whead) != null && h.status != 0)
576 release(h);
577 return;
578 }
579 }
580 else if (tryDecReaderOverflow(s) != 0L)
581 return;
582 }
583 throw new IllegalMonitorStateException();
584 }
585
586 /**
587 * If the lock state matches the given stamp, performs one of
588 * the following actions. If the stamp represents holding a write
589 * lock, returns it. Or, if a read lock, if the write lock is
590 * available, releases the read lock and returns a write stamp.
591 * Or, if an optimistic read, returns a write stamp only if
592 * immediately available. This method returns zero in all other
593 * cases.
594 *
595 * @param stamp a stamp
596 * @return a valid write stamp, or zero on failure
597 */
598 public long tryConvertToWriteLock(long stamp) {
599 long a = stamp & ABITS, m, s, next;
600 while (((s = state) & SBITS) == (stamp & SBITS)) {
601 if ((m = s & ABITS) == 0L) {
602 if (a != 0L)
603 break;
604 if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
605 return next;
606 }
607 else if (m == WBIT) {
608 if (a != m)
609 break;
610 return stamp;
611 }
612 else if (m == RUNIT && a != 0L) {
613 if (U.compareAndSwapLong(this, STATE, s,
614 next = s - RUNIT + WBIT))
615 return next;
616 }
617 else
618 break;
619 }
620 return 0L;
621 }
622
623 /**
624 * If the lock state matches the given stamp, performs one of
625 * the following actions. If the stamp represents holding a write
626 * lock, releases it and obtains a read lock. Or, if a read lock,
627 * returns it. Or, if an optimistic read, acquires a read lock and
628 * returns a read stamp only if immediately available. This method
629 * returns zero in all other cases.
630 *
631 * @param stamp a stamp
632 * @return a valid read stamp, or zero on failure
633 */
634 public long tryConvertToReadLock(long stamp) {
635 long a = stamp & ABITS, m, s, next; WNode h;
636 while (((s = state) & SBITS) == (stamp & SBITS)) {
637 if ((m = s & ABITS) == 0L) {
638 if (a != 0L)
639 break;
640 else if (m < RFULL) {
641 if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
642 return next;
643 }
644 else if ((next = tryIncReaderOverflow(s)) != 0L)
645 return next;
646 }
647 else if (m == WBIT) {
648 if (a != m)
649 break;
650 state = next = s + (WBIT + RUNIT);
651 if ((h = whead) != null && h.status != 0)
652 release(h);
653 return next;
654 }
655 else if (a != 0L && a < WBIT)
656 return stamp;
657 else
658 break;
659 }
660 return 0L;
661 }
662
663 /**
664 * If the lock state matches the given stamp then, if the stamp
665 * represents holding a lock, releases it and returns an
666 * observation stamp. Or, if an optimistic read, returns it if
667 * validated. This method returns zero in all other cases, and so
668 * may be useful as a form of "tryUnlock".
669 *
670 * @param stamp a stamp
671 * @return a valid optimistic read stamp, or zero on failure
672 */
673 public long tryConvertToOptimisticRead(long stamp) {
674 long a = stamp & ABITS, m, s, next; WNode h;
675 for (;;) {
676 s = U.getLongVolatile(this, STATE); // see above
677 if (((s = state) & SBITS) != (stamp & SBITS))
678 break;
679 if ((m = s & ABITS) == 0L) {
680 if (a != 0L)
681 break;
682 return s;
683 }
684 else if (m == WBIT) {
685 if (a != m)
686 break;
687 state = next = (s += WBIT) == 0L ? ORIGIN : s;
688 if ((h = whead) != null && h.status != 0)
689 release(h);
690 return next;
691 }
692 else if (a == 0L || a >= WBIT)
693 break;
694 else if (m < RFULL) {
695 if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
696 if (m == RUNIT && (h = whead) != null && h.status != 0)
697 release(h);
698 return next & SBITS;
699 }
700 }
701 else if ((next = tryDecReaderOverflow(s)) != 0L)
702 return next & SBITS;
703 }
704 return 0L;
705 }
706
707 /**
708 * Releases the write lock if it is held, without requiring a
709 * stamp value. This method may be useful for recovery after
710 * errors.
711 *
712 * @return {@code true} if the lock was held, else false
713 */
714 public boolean tryUnlockWrite() {
715 long s; WNode h;
716 if (((s = state) & WBIT) != 0L) {
717 state = (s += WBIT) == 0L ? ORIGIN : s;
718 if ((h = whead) != null && h.status != 0)
719 release(h);
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 * @return {@code true} if the read lock was held, else false
731 */
732 public boolean tryUnlockRead() {
733 long s, m; WNode h;
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 && (h = whead) != null && h.status != 0)
738 release(h);
739 return true;
740 }
741 }
742 else if (tryDecReaderOverflow(s) != 0L)
743 return true;
744 }
745 return false;
746 }
747
748 // status monitoring methods
749
750 /**
751 * Returns combined state-held and overflow read count for given
752 * state s.
753 */
754 private int getReadLockCount(long s) {
755 long readers;
756 if ((readers = s & RBITS) >= RFULL)
757 readers = RFULL + readerOverflow;
758 return (int) readers;
759 }
760
761 /**
762 * Returns {@code true} if the lock is currently held exclusively.
763 *
764 * @return {@code true} if the lock is currently held exclusively
765 */
766 public boolean isWriteLocked() {
767 return (state & WBIT) != 0L;
768 }
769
770 /**
771 * Returns {@code true} if the lock is currently held non-exclusively.
772 *
773 * @return {@code true} if the lock is currently held non-exclusively
774 */
775 public boolean isReadLocked() {
776 return (state & RBITS) != 0L;
777 }
778
779 /**
780 * Queries the number of read locks held for this lock. This
781 * method is designed for use in monitoring system state, not for
782 * synchronization control.
783 * @return the number of read locks held
784 */
785 public int getReadLockCount() {
786 return getReadLockCount(state);
787 }
788
789 /**
790 * Returns a string identifying this lock, as well as its lock
791 * state. The state, in brackets, includes the String {@code
792 * "Unlocked"} or the String {@code "Write-locked"} or the String
793 * {@code "Read-locks:"} followed by the current number of
794 * read-locks held.
795 *
796 * @return a string identifying this lock, as well as its lock state
797 */
798 public String toString() {
799 long s = state;
800 return super.toString() +
801 ((s & ABITS) == 0L ? "[Unlocked]" :
802 (s & WBIT) != 0L ? "[Write-locked]" :
803 "[Read-locks:" + getReadLockCount(s) + "]");
804 }
805
806 // views
807
808 /**
809 * Returns a plain {@link Lock} view of this StampedLock in which
810 * the {@link Lock#lock} method is mapped to {@link #readLock},
811 * and similarly for other methods. The returned Lock does not
812 * support a {@link Condition}; method {@link
813 * Lock#newCondition()} throws {@code
814 * UnsupportedOperationException}.
815 *
816 * @return the lock
817 */
818 public Lock asReadLock() {
819 ReadLockView v;
820 return ((v = readLockView) != null ? v :
821 (readLockView = new ReadLockView()));
822 }
823
824 /**
825 * Returns a plain {@link Lock} view of this StampedLock in which
826 * the {@link Lock#lock} method is mapped to {@link #writeLock},
827 * and similarly for other methods. The returned Lock does not
828 * support a {@link Condition}; method {@link
829 * Lock#newCondition()} throws {@code
830 * UnsupportedOperationException}.
831 *
832 * @return the lock
833 */
834 public Lock asWriteLock() {
835 WriteLockView v;
836 return ((v = writeLockView) != null ? v :
837 (writeLockView = new WriteLockView()));
838 }
839
840 /**
841 * Returns a {@link ReadWriteLock} view of this StampedLock in
842 * which the {@link ReadWriteLock#readLock()} method is mapped to
843 * {@link #asReadLock()}, and {@link ReadWriteLock#writeLock()} to
844 * {@link #asWriteLock()}.
845 *
846 * @return the lock
847 */
848 public ReadWriteLock asReadWriteLock() {
849 ReadWriteLockView v;
850 return ((v = readWriteLockView) != null ? v :
851 (readWriteLockView = new ReadWriteLockView()));
852 }
853
854 // view classes
855
856 final class ReadLockView implements Lock {
857 public void lock() { readLock(); }
858 public void lockInterruptibly() throws InterruptedException {
859 readLockInterruptibly();
860 }
861 public boolean tryLock() { return tryReadLock() != 0L; }
862 public boolean tryLock(long time, TimeUnit unit)
863 throws InterruptedException {
864 return tryReadLock(time, unit) != 0L;
865 }
866 public void unlock() { unstampedUnlockRead(); }
867 public Condition newCondition() {
868 throw new UnsupportedOperationException();
869 }
870 }
871
872 final class WriteLockView implements Lock {
873 public void lock() { writeLock(); }
874 public void lockInterruptibly() throws InterruptedException {
875 writeLockInterruptibly();
876 }
877 public boolean tryLock() { return tryWriteLock() != 0L; }
878 public boolean tryLock(long time, TimeUnit unit)
879 throws InterruptedException {
880 return tryWriteLock(time, unit) != 0L;
881 }
882 public void unlock() { unstampedUnlockWrite(); }
883 public Condition newCondition() {
884 throw new UnsupportedOperationException();
885 }
886 }
887
888 final class ReadWriteLockView implements ReadWriteLock {
889 public Lock readLock() { return asReadLock(); }
890 public Lock writeLock() { return asWriteLock(); }
891 }
892
893 // Unlock methods without stamp argument checks for view classes.
894 // Needed because view-class lock methods throw away stamps.
895
896 final void unstampedUnlockWrite() {
897 WNode h; long s;
898 if (((s = state) & WBIT) == 0L)
899 throw new IllegalMonitorStateException();
900 state = (s += WBIT) == 0L ? ORIGIN : s;
901 if ((h = whead) != null && h.status != 0)
902 release(h);
903 }
904
905 final void unstampedUnlockRead() {
906 for (;;) {
907 long s, m; WNode h;
908 if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
909 throw new IllegalMonitorStateException();
910 else if (m < RFULL) {
911 if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
912 if (m == RUNIT && (h = whead) != null && h.status != 0)
913 release(h);
914 break;
915 }
916 }
917 else if (tryDecReaderOverflow(s) != 0L)
918 break;
919 }
920 }
921
922 private void readObject(java.io.ObjectInputStream s)
923 throws java.io.IOException, ClassNotFoundException {
924 s.defaultReadObject();
925 state = ORIGIN; // reset to unlocked state
926 }
927
928 // internals
929
930 /**
931 * Tries to increment readerOverflow by first setting state
932 * access bits value to RBITS, indicating hold of spinlock,
933 * then updating, then releasing.
934 *
935 * @param s a reader overflow stamp: (s & ABITS) >= RFULL
936 * @return new stamp on success, else zero
937 */
938 private long tryIncReaderOverflow(long s) {
939 // assert (s & ABITS) >= RFULL;
940 if ((s & ABITS) == RFULL) {
941 if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
942 ++readerOverflow;
943 state = s;
944 return s;
945 }
946 }
947 else if ((ThreadLocalRandom.current().nextInt() &
948 OVERFLOW_YIELD_RATE) == 0)
949 Thread.yield();
950 return 0L;
951 }
952
953 /**
954 * Tries to decrement readerOverflow.
955 *
956 * @param s a reader overflow stamp: (s & ABITS) >= RFULL
957 * @return new stamp on success, else zero
958 */
959 private long tryDecReaderOverflow(long s) {
960 // assert (s & ABITS) >= RFULL;
961 if ((s & ABITS) == RFULL) {
962 if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
963 int r; long next;
964 if ((r = readerOverflow) > 0) {
965 readerOverflow = r - 1;
966 next = s;
967 }
968 else
969 next = s - RUNIT;
970 state = next;
971 return next;
972 }
973 }
974 else if ((ThreadLocalRandom.current().nextInt() &
975 OVERFLOW_YIELD_RATE) == 0)
976 Thread.yield();
977 return 0L;
978 }
979
980 /**
981 * Wakes up the successor of h (normally whead). This is normally
982 * just h.next, but may require traversal from wtail if next
983 * pointers are lagging. This may fail to wake up an acquiring
984 * thread when one or more have been cancelled, but the cancel
985 * methods themselves provide extra safeguards to ensure liveness.
986 */
987 private void release(WNode h) {
988 if (h != null) {
989 WNode q; Thread w;
990 U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
991 if ((q = h.next) == null || q.status == CANCELLED) {
992 for (WNode t = wtail; t != null && t != h; t = t.prev)
993 if (t.status <= 0)
994 q = t;
995 }
996 if (q != null && (w = q.thread) != null)
997 U.unpark(w);
998 }
999 }
1000
1001 /**
1002 * See above for explanation.
1003 *
1004 * @param interruptible true if should check interrupts and if so
1005 * return INTERRUPTED
1006 * @param deadline if nonzero, the System.nanoTime value to timeout
1007 * at (and return zero)
1008 * @return next state, or INTERRUPTED
1009 */
1010 private long acquireWrite(boolean interruptible, long deadline) {
1011 WNode node = null, p;
1012 for (int spins = -1;;) { // spin while enqueuing
1013 long m, s, ns;
1014 if ((m = (s = state) & ABITS) == 0L) {
1015 if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
1016 return ns;
1017 }
1018 else if (spins < 0)
1019 spins = (m == WBIT && wtail == whead) ? SPINS : 0;
1020 else if (spins > 0) {
1021 if (ThreadLocalRandom.current().nextInt() >= 0)
1022 --spins;
1023 }
1024 else if ((p = wtail) == null) { // initialize queue
1025 WNode hd = new WNode(WMODE, null);
1026 if (U.compareAndSwapObject(this, WHEAD, null, hd))
1027 wtail = hd;
1028 }
1029 else if (node == null)
1030 node = new WNode(WMODE, p);
1031 else if (node.prev != p)
1032 node.prev = p;
1033 else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
1034 p.next = node;
1035 break;
1036 }
1037 }
1038
1039 for (int spins = -1;;) {
1040 WNode h, np, pp; int ps;
1041 if ((h = whead) == p) {
1042 if (spins < 0)
1043 spins = HEAD_SPINS;
1044 else if (spins < MAX_HEAD_SPINS)
1045 spins <<= 1;
1046 for (int k = spins;;) { // spin at head
1047 long s, ns;
1048 if (((s = state) & ABITS) == 0L) {
1049 if (U.compareAndSwapLong(this, STATE, s,
1050 ns = s + WBIT)) {
1051 whead = node;
1052 node.prev = null;
1053 return ns;
1054 }
1055 }
1056 else if (ThreadLocalRandom.current().nextInt() >= 0 &&
1057 --k <= 0)
1058 break;
1059 }
1060 }
1061 else if (h != null) { // help release stale waiters
1062 WNode c; Thread w;
1063 while ((c = h.cowait) != null) {
1064 if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1065 (w = c.thread) != null)
1066 U.unpark(w);
1067 }
1068 }
1069 if (whead == h) {
1070 if ((np = node.prev) != p) {
1071 if (np != null)
1072 (p = np).next = node; // stale
1073 }
1074 else if ((ps = p.status) == 0)
1075 U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
1076 else if (ps == CANCELLED) {
1077 if ((pp = p.prev) != null) {
1078 node.prev = pp;
1079 pp.next = node;
1080 }
1081 }
1082 else {
1083 long time; // 0 argument to park means no timeout
1084 if (deadline == 0L)
1085 time = 0L;
1086 else if ((time = deadline - System.nanoTime()) <= 0L)
1087 return cancelWaiter(node, node, false);
1088 Thread wt = Thread.currentThread();
1089 U.putObject(wt, PARKBLOCKER, this);
1090 node.thread = wt;
1091 if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
1092 whead == h && node.prev == p)
1093 U.park(false, time); // emulate LockSupport.park
1094 node.thread = null;
1095 U.putObject(wt, PARKBLOCKER, null);
1096 if (interruptible && Thread.interrupted())
1097 return cancelWaiter(node, node, true);
1098 }
1099 }
1100 }
1101 }
1102
1103 /**
1104 * See above for explanation.
1105 *
1106 * @param interruptible true if should check interrupts and if so
1107 * return INTERRUPTED
1108 * @param deadline if nonzero, the System.nanoTime value to timeout
1109 * at (and return zero)
1110 * @return next state, or INTERRUPTED
1111 */
1112 private long acquireRead(boolean interruptible, long deadline) {
1113 WNode node = null, p;
1114 for (int spins = -1;;) {
1115 WNode h;
1116 if ((h = whead) == (p = wtail)) {
1117 for (long m, s, ns;;) {
1118 if ((m = (s = state) & ABITS) < RFULL ?
1119 U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
1120 (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L))
1121 return ns;
1122 else if (m >= WBIT) {
1123 if (spins > 0) {
1124 if (ThreadLocalRandom.current().nextInt() >= 0)
1125 --spins;
1126 }
1127 else {
1128 if (spins == 0) {
1129 WNode nh = whead, np = wtail;
1130 if ((nh == h && np == p) || (h = nh) != (p = np))
1131 break;
1132 }
1133 spins = SPINS;
1134 }
1135 }
1136 }
1137 }
1138 if (p == null) { // initialize queue
1139 WNode hd = new WNode(WMODE, null);
1140 if (U.compareAndSwapObject(this, WHEAD, null, hd))
1141 wtail = hd;
1142 }
1143 else if (node == null)
1144 node = new WNode(RMODE, p);
1145 else if (h == p || p.mode != RMODE) {
1146 if (node.prev != p)
1147 node.prev = p;
1148 else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
1149 p.next = node;
1150 break;
1151 }
1152 }
1153 else if (!U.compareAndSwapObject(p, WCOWAIT,
1154 node.cowait = p.cowait, node))
1155 node.cowait = null;
1156 else {
1157 for (;;) {
1158 WNode pp, c; Thread w;
1159 if ((h = whead) != null && (c = h.cowait) != null &&
1160 U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1161 (w = c.thread) != null) // help release
1162 U.unpark(w);
1163 if (h == (pp = p.prev) || h == p || pp == null) {
1164 long m, s, ns;
1165 do {
1166 if ((m = (s = state) & ABITS) < RFULL ?
1167 U.compareAndSwapLong(this, STATE, s,
1168 ns = s + RUNIT) :
1169 (m < WBIT &&
1170 (ns = tryIncReaderOverflow(s)) != 0L))
1171 return ns;
1172 } while (m < WBIT);
1173 }
1174 if (whead == h && p.prev == pp) {
1175 long time;
1176 if (pp == null || h == p || p.status > 0) {
1177 node = null; // throw away
1178 break;
1179 }
1180 if (deadline == 0L)
1181 time = 0L;
1182 else if ((time = deadline - System.nanoTime()) <= 0L)
1183 return cancelWaiter(node, p, false);
1184 Thread wt = Thread.currentThread();
1185 U.putObject(wt, PARKBLOCKER, this);
1186 node.thread = wt;
1187 if ((h != pp || (state & ABITS) == WBIT) &&
1188 whead == h && p.prev == pp)
1189 U.park(false, time);
1190 node.thread = null;
1191 U.putObject(wt, PARKBLOCKER, null);
1192 if (interruptible && Thread.interrupted())
1193 return cancelWaiter(node, p, true);
1194 }
1195 }
1196 }
1197 }
1198
1199 for (int spins = -1;;) {
1200 WNode h, np, pp; int ps;
1201 if ((h = whead) == p) {
1202 if (spins < 0)
1203 spins = HEAD_SPINS;
1204 else if (spins < MAX_HEAD_SPINS)
1205 spins <<= 1;
1206 for (int k = spins;;) { // spin at head
1207 long m, s, ns;
1208 if ((m = (s = state) & ABITS) < RFULL ?
1209 U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
1210 (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
1211 WNode c; Thread w;
1212 whead = node;
1213 node.prev = null;
1214 while ((c = node.cowait) != null) {
1215 if (U.compareAndSwapObject(node, WCOWAIT,
1216 c, c.cowait) &&
1217 (w = c.thread) != null)
1218 U.unpark(w);
1219 }
1220 return ns;
1221 }
1222 else if (m >= WBIT &&
1223 ThreadLocalRandom.current().nextInt() >= 0 && --k <= 0)
1224 break;
1225 }
1226 }
1227 else if (h != null) {
1228 WNode c; Thread w;
1229 while ((c = h.cowait) != null) {
1230 if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
1231 (w = c.thread) != null)
1232 U.unpark(w);
1233 }
1234 }
1235 if (whead == h) {
1236 if ((np = node.prev) != p) {
1237 if (np != null)
1238 (p = np).next = node; // stale
1239 }
1240 else if ((ps = p.status) == 0)
1241 U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
1242 else if (ps == CANCELLED) {
1243 if ((pp = p.prev) != null) {
1244 node.prev = pp;
1245 pp.next = node;
1246 }
1247 }
1248 else {
1249 long time;
1250 if (deadline == 0L)
1251 time = 0L;
1252 else if ((time = deadline - System.nanoTime()) <= 0L)
1253 return cancelWaiter(node, node, false);
1254 Thread wt = Thread.currentThread();
1255 U.putObject(wt, PARKBLOCKER, this);
1256 node.thread = wt;
1257 if (p.status < 0 &&
1258 (p != h || (state & ABITS) == WBIT) &&
1259 whead == h && node.prev == p)
1260 U.park(false, time);
1261 node.thread = null;
1262 U.putObject(wt, PARKBLOCKER, null);
1263 if (interruptible && Thread.interrupted())
1264 return cancelWaiter(node, node, true);
1265 }
1266 }
1267 }
1268 }
1269
1270 /**
1271 * If node non-null, forces cancel status and unsplices it from
1272 * queue if possible and wakes up any cowaiters (of the node, or
1273 * group, as applicable), and in any case helps release current
1274 * first waiter if lock is free. (Calling with null arguments
1275 * serves as a conditional form of release, which is not currently
1276 * needed but may be needed under possible future cancellation
1277 * policies). This is a variant of cancellation methods in
1278 * AbstractQueuedSynchronizer (see its detailed explanation in AQS
1279 * internal documentation).
1280 *
1281 * @param node if nonnull, the waiter
1282 * @param group either node or the group node is cowaiting with
1283 * @param interrupted if already interrupted
1284 * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
1285 */
1286 private long cancelWaiter(WNode node, WNode group, boolean interrupted) {
1287 if (node != null && group != null) {
1288 Thread w;
1289 node.status = CANCELLED;
1290 // unsplice cancelled nodes from group
1291 for (WNode p = group, q; (q = p.cowait) != null;) {
1292 if (q.status == CANCELLED) {
1293 U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
1294 p = group; // restart
1295 }
1296 else
1297 p = q;
1298 }
1299 if (group == node) {
1300 for (WNode r = group.cowait; r != null; r = r.cowait) {
1301 if ((w = r.thread) != null)
1302 U.unpark(w); // wake up uncancelled co-waiters
1303 }
1304 for (WNode pred = node.prev; pred != null; ) { // unsplice
1305 WNode succ, pp; // find valid successor
1306 while ((succ = node.next) == null ||
1307 succ.status == CANCELLED) {
1308 WNode q = null; // find successor the slow way
1309 for (WNode t = wtail; t != null && t != node; t = t.prev)
1310 if (t.status != CANCELLED)
1311 q = t; // don't link if succ cancelled
1312 if (succ == q || // ensure accurate successor
1313 U.compareAndSwapObject(node, WNEXT,
1314 succ, succ = q)) {
1315 if (succ == null && node == wtail)
1316 U.compareAndSwapObject(this, WTAIL, node, pred);
1317 break;
1318 }
1319 }
1320 if (pred.next == node) // unsplice pred link
1321 U.compareAndSwapObject(pred, WNEXT, node, succ);
1322 if (succ != null && (w = succ.thread) != null) {
1323 succ.thread = null;
1324 U.unpark(w); // wake up succ to observe new pred
1325 }
1326 if (pred.status != CANCELLED || (pp = pred.prev) == null)
1327 break;
1328 node.prev = pp; // repeat if new pred wrong/cancelled
1329 U.compareAndSwapObject(pp, WNEXT, pred, succ);
1330 pred = pp;
1331 }
1332 }
1333 }
1334 WNode h; // Possibly release first waiter
1335 while ((h = whead) != null) {
1336 long s; WNode q; // similar to release() but check eligibility
1337 if ((q = h.next) == null || q.status == CANCELLED) {
1338 for (WNode t = wtail; t != null && t != h; t = t.prev)
1339 if (t.status <= 0)
1340 q = t;
1341 }
1342 if (h == whead) {
1343 if (q != null && h.status == 0 &&
1344 ((s = state) & ABITS) != WBIT && // waiter is eligible
1345 (s == 0L || q.mode == RMODE))
1346 release(h);
1347 break;
1348 }
1349 }
1350 return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
1351 }
1352
1353 // Unsafe mechanics
1354 private static final sun.misc.Unsafe U;
1355 private static final long STATE;
1356 private static final long WHEAD;
1357 private static final long WTAIL;
1358 private static final long WNEXT;
1359 private static final long WSTATUS;
1360 private static final long WCOWAIT;
1361 private static final long PARKBLOCKER;
1362
1363 static {
1364 try {
1365 U = getUnsafe();
1366 Class<?> k = StampedLock.class;
1367 Class<?> wk = WNode.class;
1368 STATE = U.objectFieldOffset
1369 (k.getDeclaredField("state"));
1370 WHEAD = U.objectFieldOffset
1371 (k.getDeclaredField("whead"));
1372 WTAIL = U.objectFieldOffset
1373 (k.getDeclaredField("wtail"));
1374 WSTATUS = U.objectFieldOffset
1375 (wk.getDeclaredField("status"));
1376 WNEXT = U.objectFieldOffset
1377 (wk.getDeclaredField("next"));
1378 WCOWAIT = U.objectFieldOffset
1379 (wk.getDeclaredField("cowait"));
1380 Class<?> tk = Thread.class;
1381 PARKBLOCKER = U.objectFieldOffset
1382 (tk.getDeclaredField("parkBlocker"));
1383
1384 } catch (Exception e) {
1385 throw new Error(e);
1386 }
1387 }
1388
1389 /**
1390 * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
1391 * Replace with a simple call to Unsafe.getUnsafe when integrating
1392 * into a jdk.
1393 *
1394 * @return a sun.misc.Unsafe
1395 */
1396 private static sun.misc.Unsafe getUnsafe() {
1397 try {
1398 return sun.misc.Unsafe.getUnsafe();
1399 } catch (SecurityException tryReflectionInstead) {}
1400 try {
1401 return java.security.AccessController.doPrivileged
1402 (new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
1403 public sun.misc.Unsafe run() throws Exception {
1404 Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
1405 for (java.lang.reflect.Field f : k.getDeclaredFields()) {
1406 f.setAccessible(true);
1407 Object x = f.get(null);
1408 if (k.isInstance(x))
1409 return k.cast(x);
1410 }
1411 throw new NoSuchFieldError("the Unsafe");
1412 }});
1413 } catch (java.security.PrivilegedActionException e) {
1414 throw new RuntimeException("Could not initialize intrinsics",
1415 e.getCause());
1416 }
1417 }
1418 }