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