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