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