src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java
author dl
Thu, 02 May 2019 06:33:28 -0700
changeset 54685 e1bec7613945
parent 47216 71c04702a3d5
permissions -rw-r--r--
8220248: fix headings in java.util.concurrent Reviewed-by: martin, jjg
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     1
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90ce3da70b43 Initial load
duke
parents:
diff changeset
     3
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
     4
 * This code is free software; you can redistribute it and/or modify it
90ce3da70b43 Initial load
duke
parents:
diff changeset
     5
 * under the terms of the GNU General Public License version 2 only, as
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2431
diff changeset
     6
 * published by the Free Software Foundation.  Oracle designates this
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     7
 * particular file as subject to the "Classpath" exception as provided
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2431
diff changeset
     8
 * by Oracle in the LICENSE file that accompanied this code.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
     9
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    10
 * This code is distributed in the hope that it will be useful, but WITHOUT
90ce3da70b43 Initial load
duke
parents:
diff changeset
    11
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    12
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
90ce3da70b43 Initial load
duke
parents:
diff changeset
    13
 * version 2 for more details (a copy is included in the LICENSE file that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    14
 * accompanied this code).
90ce3da70b43 Initial load
duke
parents:
diff changeset
    15
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    16
 * You should have received a copy of the GNU General Public License version
90ce3da70b43 Initial load
duke
parents:
diff changeset
    17
 * 2 along with this work; if not, write to the Free Software Foundation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
    18
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    19
 *
5506
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2431
diff changeset
    20
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2431
diff changeset
    21
 * or visit www.oracle.com if you need additional information or have any
202f599c92aa 6943119: Rebrand source copyright notices
ohair
parents: 2431
diff changeset
    22
 * questions.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    23
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    24
90ce3da70b43 Initial load
duke
parents:
diff changeset
    25
/*
90ce3da70b43 Initial load
duke
parents:
diff changeset
    26
 * This file is available under and governed by the GNU General Public
90ce3da70b43 Initial load
duke
parents:
diff changeset
    27
 * License version 2 only, as published by the Free Software Foundation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    28
 * However, the following notice accompanied the original version of this
90ce3da70b43 Initial load
duke
parents:
diff changeset
    29
 * file:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    30
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    31
 * Written by Doug Lea with assistance from members of JCP JSR-166
90ce3da70b43 Initial load
duke
parents:
diff changeset
    32
 * Expert Group and released to the public domain, as explained at
9242
ef138d47df58 7034657: Update Creative Commons license URL in legal notices
dl
parents: 7518
diff changeset
    33
 * http://creativecommons.org/publicdomain/zero/1.0/
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    34
 */
90ce3da70b43 Initial load
duke
parents:
diff changeset
    35
90ce3da70b43 Initial load
duke
parents:
diff changeset
    36
package java.util.concurrent.locks;
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
    37
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
    38
import java.util.Collection;
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
    39
import java.util.concurrent.TimeUnit;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
    40
import jdk.internal.vm.annotation.ReservedStackAccess;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    41
90ce3da70b43 Initial load
duke
parents:
diff changeset
    42
/**
90ce3da70b43 Initial load
duke
parents:
diff changeset
    43
 * An implementation of {@link ReadWriteLock} supporting similar
90ce3da70b43 Initial load
duke
parents:
diff changeset
    44
 * semantics to {@link ReentrantLock}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    45
 * <p>This class has the following properties:
90ce3da70b43 Initial load
duke
parents:
diff changeset
    46
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    47
 * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    48
 * <li><b>Acquisition order</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    49
 *
18575
2ab0d0b3ecad 8017739: ReentrantReadWriteLock is confused by the Threads with reused IDs
dl
parents: 14325
diff changeset
    50
 * <p>This class does not impose a reader or writer preference
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    51
 * ordering for lock access.  However, it does support an optional
90ce3da70b43 Initial load
duke
parents:
diff changeset
    52
 * <em>fairness</em> policy.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    53
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    54
 * <dl>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    55
 * <dt><b><i>Non-fair mode (default)</i></b>
44039
058585425bb7 8173909: Miscellaneous changes imported from jsr166 CVS 2017-03
dl
parents: 42927
diff changeset
    56
 * <dd>When constructed as non-fair (the default), the order of entry
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    57
 * to the read and write lock is unspecified, subject to reentrancy
90ce3da70b43 Initial load
duke
parents:
diff changeset
    58
 * constraints.  A nonfair lock that is continuously contended may
90ce3da70b43 Initial load
duke
parents:
diff changeset
    59
 * indefinitely postpone one or more reader or writer threads, but
90ce3da70b43 Initial load
duke
parents:
diff changeset
    60
 * will normally have higher throughput than a fair lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    61
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    62
 * <dt><b><i>Fair mode</i></b>
44039
058585425bb7 8173909: Miscellaneous changes imported from jsr166 CVS 2017-03
dl
parents: 42927
diff changeset
    63
 * <dd>When constructed as fair, threads contend for entry using an
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    64
 * approximately arrival-order policy. When the currently held lock
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
    65
 * is released, either the longest-waiting single writer thread will
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    66
 * be assigned the write lock, or if there is a group of reader threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
    67
 * waiting longer than all waiting writer threads, that group will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    68
 * assigned the read lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    69
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    70
 * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    71
 * will block if either the write lock is held, or there is a waiting
90ce3da70b43 Initial load
duke
parents:
diff changeset
    72
 * writer thread. The thread will not acquire the read lock until
90ce3da70b43 Initial load
duke
parents:
diff changeset
    73
 * after the oldest currently waiting writer thread has acquired and
90ce3da70b43 Initial load
duke
parents:
diff changeset
    74
 * released the write lock. Of course, if a waiting writer abandons
90ce3da70b43 Initial load
duke
parents:
diff changeset
    75
 * its wait, leaving one or more reader threads as the longest waiters
90ce3da70b43 Initial load
duke
parents:
diff changeset
    76
 * in the queue with the write lock free, then those readers will be
90ce3da70b43 Initial load
duke
parents:
diff changeset
    77
 * assigned the read lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    78
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    79
 * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
90ce3da70b43 Initial load
duke
parents:
diff changeset
    80
 * will block unless both the read lock and write lock are free (which
90ce3da70b43 Initial load
duke
parents:
diff changeset
    81
 * implies there are no waiting threads).  (Note that the non-blocking
90ce3da70b43 Initial load
duke
parents:
diff changeset
    82
 * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
    83
 * do not honor this fair setting and will immediately acquire the lock
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
    84
 * if it is possible, regardless of waiting threads.)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
    85
 * </dl>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    86
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    87
 * <li><b>Reentrancy</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
    88
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    89
 * <p>This lock allows both readers and writers to reacquire read or
90ce3da70b43 Initial load
duke
parents:
diff changeset
    90
 * write locks in the style of a {@link ReentrantLock}. Non-reentrant
90ce3da70b43 Initial load
duke
parents:
diff changeset
    91
 * readers are not allowed until all write locks held by the writing
90ce3da70b43 Initial load
duke
parents:
diff changeset
    92
 * thread have been released.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    93
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
    94
 * <p>Additionally, a writer can acquire the read lock, but not
90ce3da70b43 Initial load
duke
parents:
diff changeset
    95
 * vice-versa.  Among other applications, reentrancy can be useful
90ce3da70b43 Initial load
duke
parents:
diff changeset
    96
 * when write locks are held during calls or callbacks to methods that
90ce3da70b43 Initial load
duke
parents:
diff changeset
    97
 * perform reads under read locks.  If a reader tries to acquire the
90ce3da70b43 Initial load
duke
parents:
diff changeset
    98
 * write lock it will never succeed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
    99
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   100
 * <li><b>Lock downgrading</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   101
 * <p>Reentrancy also allows downgrading from the write lock to a read lock,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   102
 * by acquiring the write lock, then the read lock and then releasing the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   103
 * write lock. However, upgrading from a read lock to the write lock is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   104
 * <b>not</b> possible.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   105
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   106
 * <li><b>Interruption of lock acquisition</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   107
 * <p>The read lock and write lock both support interruption during lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   108
 * acquisition.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   109
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   110
 * <li><b>{@link Condition} support</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   111
 * <p>The write lock provides a {@link Condition} implementation that
90ce3da70b43 Initial load
duke
parents:
diff changeset
   112
 * behaves in the same way, with respect to the write lock, as the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   113
 * {@link Condition} implementation provided by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   114
 * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   115
 * This {@link Condition} can, of course, only be used with the write lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   116
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   117
 * <p>The read lock does not support a {@link Condition} and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   118
 * {@code readLock().newCondition()} throws
90ce3da70b43 Initial load
duke
parents:
diff changeset
   119
 * {@code UnsupportedOperationException}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   120
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   121
 * <li><b>Instrumentation</b>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   122
 * <p>This class supports methods to determine whether locks
90ce3da70b43 Initial load
duke
parents:
diff changeset
   123
 * are held or contended. These methods are designed for monitoring
90ce3da70b43 Initial load
duke
parents:
diff changeset
   124
 * system state, not for synchronization control.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   125
 * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   126
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   127
 * <p>Serialization of this class behaves in the same way as built-in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   128
 * locks: a deserialized lock is in the unlocked state, regardless of
90ce3da70b43 Initial load
duke
parents:
diff changeset
   129
 * its state when serialized.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   130
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   131
 * <p><b>Sample usages</b>. Here is a code sketch showing how to perform
90ce3da70b43 Initial load
duke
parents:
diff changeset
   132
 * lock downgrading after updating a cache (exception handling is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   133
 * particularly tricky when handling multiple locks in a non-nested
90ce3da70b43 Initial load
duke
parents:
diff changeset
   134
 * fashion):
90ce3da70b43 Initial load
duke
parents:
diff changeset
   135
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   136
 * <pre> {@code
90ce3da70b43 Initial load
duke
parents:
diff changeset
   137
 * class CachedData {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   138
 *   Object data;
42927
1d31e540bfcb 8170484: Miscellaneous changes imported from jsr166 CVS 2016-12
dl
parents: 39725
diff changeset
   139
 *   boolean cacheValid;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   140
 *   final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   141
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   142
 *   void processCachedData() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   143
 *     rwl.readLock().lock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   144
 *     if (!cacheValid) {
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   145
 *       // Must release read lock before acquiring write lock
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   146
 *       rwl.readLock().unlock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   147
 *       rwl.writeLock().lock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   148
 *       try {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   149
 *         // Recheck state because another thread might have
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   150
 *         // acquired write lock and changed state before we did.
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   151
 *         if (!cacheValid) {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   152
 *           data = ...
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   153
 *           cacheValid = true;
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   154
 *         }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   155
 *         // Downgrade by acquiring read lock before releasing write lock
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   156
 *         rwl.readLock().lock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   157
 *       } finally {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   158
 *         rwl.writeLock().unlock(); // Unlock write, still hold read
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   159
 *       }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   160
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   161
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   162
 *     try {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   163
 *       use(data);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   164
 *     } finally {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   165
 *       rwl.readLock().unlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   166
 *     }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   167
 *   }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   168
 * }}</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   169
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   170
 * ReentrantReadWriteLocks can be used to improve concurrency in some
90ce3da70b43 Initial load
duke
parents:
diff changeset
   171
 * uses of some kinds of Collections. This is typically worthwhile
90ce3da70b43 Initial load
duke
parents:
diff changeset
   172
 * only when the collections are expected to be large, accessed by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   173
 * more reader threads than writer threads, and entail operations with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   174
 * overhead that outweighs synchronization overhead. For example, here
90ce3da70b43 Initial load
duke
parents:
diff changeset
   175
 * is a class using a TreeMap that is expected to be large and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   176
 * concurrently accessed.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   177
 *
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   178
 * <pre> {@code
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   179
 * class RWDictionary {
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   180
 *   private final Map<String, Data> m = new TreeMap<>();
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   181
 *   private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   182
 *   private final Lock r = rwl.readLock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   183
 *   private final Lock w = rwl.writeLock();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   184
 *
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   185
 *   public Data get(String key) {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   186
 *     r.lock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   187
 *     try { return m.get(key); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   188
 *     finally { r.unlock(); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   189
 *   }
34346
09f5f3df8fa8 8139574: ReentrantReadWriteLock documentation example has compile time error
dl
parents: 33674
diff changeset
   190
 *   public List<String> allKeys() {
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   191
 *     r.lock();
34346
09f5f3df8fa8 8139574: ReentrantReadWriteLock documentation example has compile time error
dl
parents: 33674
diff changeset
   192
 *     try { return new ArrayList<>(m.keySet()); }
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   193
 *     finally { r.unlock(); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   194
 *   }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   195
 *   public Data put(String key, Data value) {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   196
 *     w.lock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   197
 *     try { return m.put(key, value); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   198
 *     finally { w.unlock(); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   199
 *   }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   200
 *   public void clear() {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   201
 *     w.lock();
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   202
 *     try { m.clear(); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   203
 *     finally { w.unlock(); }
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   204
 *   }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   205
 * }}</pre>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   206
 *
54685
e1bec7613945 8220248: fix headings in java.util.concurrent
dl
parents: 47216
diff changeset
   207
 * <h2>Implementation Notes</h2>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   208
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   209
 * <p>This lock supports a maximum of 65535 recursive write locks
90ce3da70b43 Initial load
duke
parents:
diff changeset
   210
 * and 65535 read locks. Attempts to exceed these limits result in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   211
 * {@link Error} throws from locking methods.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   212
 *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   213
 * @since 1.5
90ce3da70b43 Initial load
duke
parents:
diff changeset
   214
 * @author Doug Lea
90ce3da70b43 Initial load
duke
parents:
diff changeset
   215
 */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   216
public class ReentrantReadWriteLock
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   217
        implements ReadWriteLock, java.io.Serializable {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   218
    private static final long serialVersionUID = -6992448646407690164L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   219
    /** Inner class providing readlock */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   220
    private final ReentrantReadWriteLock.ReadLock readerLock;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   221
    /** Inner class providing writelock */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   222
    private final ReentrantReadWriteLock.WriteLock writerLock;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   223
    /** Performs all synchronization mechanics */
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   224
    final Sync sync;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   225
90ce3da70b43 Initial load
duke
parents:
diff changeset
   226
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   227
     * Creates a new {@code ReentrantReadWriteLock} with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   228
     * default (nonfair) ordering properties.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   229
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   230
    public ReentrantReadWriteLock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   231
        this(false);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   232
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   233
90ce3da70b43 Initial load
duke
parents:
diff changeset
   234
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   235
     * Creates a new {@code ReentrantReadWriteLock} with
90ce3da70b43 Initial load
duke
parents:
diff changeset
   236
     * the given fairness policy.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   237
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   238
     * @param fair {@code true} if this lock should use a fair ordering policy
90ce3da70b43 Initial load
duke
parents:
diff changeset
   239
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   240
    public ReentrantReadWriteLock(boolean fair) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   241
        sync = fair ? new FairSync() : new NonfairSync();
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   242
        readerLock = new ReadLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   243
        writerLock = new WriteLock(this);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   244
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   245
90ce3da70b43 Initial load
duke
parents:
diff changeset
   246
    public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   247
    public ReentrantReadWriteLock.ReadLock  readLock()  { return readerLock; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   248
90ce3da70b43 Initial load
duke
parents:
diff changeset
   249
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   250
     * Synchronization implementation for ReentrantReadWriteLock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   251
     * Subclassed into fair and nonfair versions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   252
     */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   253
    abstract static class Sync extends AbstractQueuedSynchronizer {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   254
        private static final long serialVersionUID = 6317671515068378041L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   255
90ce3da70b43 Initial load
duke
parents:
diff changeset
   256
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   257
         * Read vs write count extraction constants and functions.
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   258
         * Lock state is logically divided into two unsigned shorts:
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   259
         * The lower one representing the exclusive (writer) lock hold count,
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   260
         * and the upper the shared (reader) hold count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   261
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   262
90ce3da70b43 Initial load
duke
parents:
diff changeset
   263
        static final int SHARED_SHIFT   = 16;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   264
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   265
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   266
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   267
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   268
        /** Returns the number of shared holds represented in count. */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   269
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   270
        /** Returns the number of exclusive holds represented in count. */
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   271
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   272
90ce3da70b43 Initial load
duke
parents:
diff changeset
   273
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   274
         * A counter for per-thread read hold counts.
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   275
         * Maintained as a ThreadLocal; cached in cachedHoldCounter.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   276
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   277
        static final class HoldCounter {
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   278
            int count;          // initially 0
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   279
            // Use id, not reference, to avoid garbage retention
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   280
            final long tid = LockSupport.getThreadId(Thread.currentThread());
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   281
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   282
90ce3da70b43 Initial load
duke
parents:
diff changeset
   283
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   284
         * ThreadLocal subclass. Easiest to explicitly define for sake
90ce3da70b43 Initial load
duke
parents:
diff changeset
   285
         * of deserialization mechanics.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   286
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   287
        static final class ThreadLocalHoldCounter
90ce3da70b43 Initial load
duke
parents:
diff changeset
   288
            extends ThreadLocal<HoldCounter> {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   289
            public HoldCounter initialValue() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   290
                return new HoldCounter();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   291
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   292
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   293
90ce3da70b43 Initial load
duke
parents:
diff changeset
   294
        /**
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   295
         * The number of reentrant read locks held by current thread.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   296
         * Initialized only in constructor and readObject.
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   297
         * Removed whenever a thread's read hold count drops to 0.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   298
         */
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   299
        private transient ThreadLocalHoldCounter readHolds;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   300
90ce3da70b43 Initial load
duke
parents:
diff changeset
   301
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   302
         * The hold count of the last thread to successfully acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   303
         * readLock. This saves ThreadLocal lookup in the common case
90ce3da70b43 Initial load
duke
parents:
diff changeset
   304
         * where the next thread to release is the last one to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   305
         * acquire. This is non-volatile since it is just used
90ce3da70b43 Initial load
duke
parents:
diff changeset
   306
         * as a heuristic, and would be great for threads to cache.
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   307
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   308
         * <p>Can outlive the Thread for which it is caching the read
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   309
         * hold count, but avoids garbage retention by not retaining a
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   310
         * reference to the Thread.
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   311
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   312
         * <p>Accessed via a benign data race; relies on the memory
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   313
         * model's final field and out-of-thin-air guarantees.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   314
         */
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   315
        private transient HoldCounter cachedHoldCounter;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   316
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   317
        /**
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   318
         * firstReader is the first thread to have acquired the read lock.
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   319
         * firstReaderHoldCount is firstReader's hold count.
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   320
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   321
         * <p>More precisely, firstReader is the unique thread that last
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   322
         * changed the shared count from 0 to 1, and has not released the
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   323
         * read lock since then; null if there is no such thread.
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   324
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   325
         * <p>Cannot cause garbage retention unless the thread terminated
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   326
         * without relinquishing its read locks, since tryReleaseShared
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   327
         * sets it to null.
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   328
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   329
         * <p>Accessed via a benign data race; relies on the memory
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   330
         * model's out-of-thin-air guarantees for references.
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   331
         *
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   332
         * <p>This allows tracking of read holds for uncontended read
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   333
         * locks to be very cheap.
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   334
         */
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   335
        private transient Thread firstReader;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   336
        private transient int firstReaderHoldCount;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   337
90ce3da70b43 Initial load
duke
parents:
diff changeset
   338
        Sync() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   339
            readHolds = new ThreadLocalHoldCounter();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   340
            setState(getState()); // ensures visibility of readHolds
90ce3da70b43 Initial load
duke
parents:
diff changeset
   341
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   342
90ce3da70b43 Initial load
duke
parents:
diff changeset
   343
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   344
         * Acquires and releases use the same code for fair and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   345
         * nonfair locks, but differ in whether/how they allow barging
90ce3da70b43 Initial load
duke
parents:
diff changeset
   346
         * when queues are non-empty.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   347
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   348
90ce3da70b43 Initial load
duke
parents:
diff changeset
   349
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   350
         * Returns true if the current thread, when trying to acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   351
         * the read lock, and otherwise eligible to do so, should block
90ce3da70b43 Initial load
duke
parents:
diff changeset
   352
         * because of policy for overtaking other waiting threads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   353
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   354
        abstract boolean readerShouldBlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   355
90ce3da70b43 Initial load
duke
parents:
diff changeset
   356
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   357
         * Returns true if the current thread, when trying to acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   358
         * the write lock, and otherwise eligible to do so, should block
90ce3da70b43 Initial load
duke
parents:
diff changeset
   359
         * because of policy for overtaking other waiting threads.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   360
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   361
        abstract boolean writerShouldBlock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   362
90ce3da70b43 Initial load
duke
parents:
diff changeset
   363
        /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   364
         * Note that tryRelease and tryAcquire can be called by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   365
         * Conditions. So it is possible that their arguments contain
90ce3da70b43 Initial load
duke
parents:
diff changeset
   366
         * both read and write holds that are all released during a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   367
         * condition wait and re-established in tryAcquire.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   368
         */
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   369
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   370
        protected final boolean tryRelease(int releases) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   371
            if (!isHeldExclusively())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   372
                throw new IllegalMonitorStateException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   373
            int nextc = getState() - releases;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   374
            boolean free = exclusiveCount(nextc) == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   375
            if (free)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   376
                setExclusiveOwnerThread(null);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   377
            setState(nextc);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   378
            return free;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   379
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   380
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   381
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   382
        protected final boolean tryAcquire(int acquires) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   383
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   384
             * Walkthrough:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   385
             * 1. If read count nonzero or write count nonzero
90ce3da70b43 Initial load
duke
parents:
diff changeset
   386
             *    and owner is a different thread, fail.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   387
             * 2. If count would saturate, fail. (This can only
90ce3da70b43 Initial load
duke
parents:
diff changeset
   388
             *    happen if count is already nonzero.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   389
             * 3. Otherwise, this thread is eligible for lock if
90ce3da70b43 Initial load
duke
parents:
diff changeset
   390
             *    it is either a reentrant acquire or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   391
             *    queue policy allows it. If so, update state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   392
             *    and set owner.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   393
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   394
            Thread current = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   395
            int c = getState();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   396
            int w = exclusiveCount(c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   397
            if (c != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   398
                // (Note: if c != 0 and w == 0 then shared count != 0)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   399
                if (w == 0 || current != getExclusiveOwnerThread())
90ce3da70b43 Initial load
duke
parents:
diff changeset
   400
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   401
                if (w + exclusiveCount(acquires) > MAX_COUNT)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   402
                    throw new Error("Maximum lock count exceeded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   403
                // Reentrant acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
   404
                setState(c + acquires);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   405
                return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   406
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   407
            if (writerShouldBlock() ||
90ce3da70b43 Initial load
duke
parents:
diff changeset
   408
                !compareAndSetState(c, c + acquires))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   409
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   410
            setExclusiveOwnerThread(current);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   411
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   412
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   413
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   414
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   415
        protected final boolean tryReleaseShared(int unused) {
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   416
            Thread current = Thread.currentThread();
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   417
            if (firstReader == current) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   418
                // assert firstReaderHoldCount > 0;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   419
                if (firstReaderHoldCount == 1)
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   420
                    firstReader = null;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   421
                else
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   422
                    firstReaderHoldCount--;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   423
            } else {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   424
                HoldCounter rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   425
                if (rh == null ||
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   426
                    rh.tid != LockSupport.getThreadId(current))
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   427
                    rh = readHolds.get();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   428
                int count = rh.count;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   429
                if (count <= 1) {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   430
                    readHolds.remove();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   431
                    if (count <= 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   432
                        throw unmatchedUnlockException();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   433
                }
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   434
                --rh.count;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   435
            }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   436
            for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   437
                int c = getState();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   438
                int nextc = c - SHARED_UNIT;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   439
                if (compareAndSetState(c, nextc))
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   440
                    // Releasing the read lock has no effect on readers,
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   441
                    // but it may allow waiting writers to proceed if
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   442
                    // both read and write locks are now free.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   443
                    return nextc == 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   444
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   445
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   446
44589
64d9270bd24c 8176543: Miscellaneous changes imported from jsr166 CVS 2017-04
dl
parents: 44039
diff changeset
   447
        private static IllegalMonitorStateException unmatchedUnlockException() {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   448
            return new IllegalMonitorStateException(
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   449
                "attempt to unlock read lock, not locked by current thread");
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   450
        }
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   451
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   452
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   453
        protected final int tryAcquireShared(int unused) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   454
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   455
             * Walkthrough:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   456
             * 1. If write lock held by another thread, fail.
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   457
             * 2. Otherwise, this thread is eligible for
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   458
             *    lock wrt state, so ask if it should block
90ce3da70b43 Initial load
duke
parents:
diff changeset
   459
             *    because of queue policy. If not, try
90ce3da70b43 Initial load
duke
parents:
diff changeset
   460
             *    to grant by CASing state and updating count.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   461
             *    Note that step does not check for reentrant
90ce3da70b43 Initial load
duke
parents:
diff changeset
   462
             *    acquires, which is postponed to full version
90ce3da70b43 Initial load
duke
parents:
diff changeset
   463
             *    to avoid having to check hold count in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   464
             *    the more typical non-reentrant case.
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   465
             * 3. If step 2 fails either because thread
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   466
             *    apparently not eligible or CAS fails or count
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   467
             *    saturated, chain to version with full retry loop.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   468
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   469
            Thread current = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   470
            int c = getState();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   471
            if (exclusiveCount(c) != 0 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   472
                getExclusiveOwnerThread() != current)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   473
                return -1;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   474
            int r = sharedCount(c);
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   475
            if (!readerShouldBlock() &&
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   476
                r < MAX_COUNT &&
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   477
                compareAndSetState(c, c + SHARED_UNIT)) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   478
                if (r == 0) {
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   479
                    firstReader = current;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   480
                    firstReaderHoldCount = 1;
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   481
                } else if (firstReader == current) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   482
                    firstReaderHoldCount++;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   483
                } else {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   484
                    HoldCounter rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   485
                    if (rh == null ||
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   486
                        rh.tid != LockSupport.getThreadId(current))
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   487
                        cachedHoldCounter = rh = readHolds.get();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   488
                    else if (rh.count == 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   489
                        readHolds.set(rh);
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   490
                    rh.count++;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   491
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   492
                return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   493
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   494
            return fullTryAcquireShared(current);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   495
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   496
90ce3da70b43 Initial load
duke
parents:
diff changeset
   497
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   498
         * Full version of acquire for reads, that handles CAS misses
90ce3da70b43 Initial load
duke
parents:
diff changeset
   499
         * and reentrant reads not dealt with in tryAcquireShared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   500
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   501
        final int fullTryAcquireShared(Thread current) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   502
            /*
90ce3da70b43 Initial load
duke
parents:
diff changeset
   503
             * This code is in part redundant with that in
90ce3da70b43 Initial load
duke
parents:
diff changeset
   504
             * tryAcquireShared but is simpler overall by not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   505
             * complicating tryAcquireShared with interactions between
90ce3da70b43 Initial load
duke
parents:
diff changeset
   506
             * retries and lazily reading hold counts.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   507
             */
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   508
            HoldCounter rh = null;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   509
            for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   510
                int c = getState();
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   511
                if (exclusiveCount(c) != 0) {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   512
                    if (getExclusiveOwnerThread() != current)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   513
                        return -1;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   514
                    // else we hold the exclusive lock; blocking here
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   515
                    // would cause deadlock.
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   516
                } else if (readerShouldBlock()) {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   517
                    // Make sure we're not acquiring read lock reentrantly
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   518
                    if (firstReader == current) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   519
                        // assert firstReaderHoldCount > 0;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   520
                    } else {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   521
                        if (rh == null) {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   522
                            rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   523
                            if (rh == null ||
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   524
                                rh.tid != LockSupport.getThreadId(current)) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   525
                                rh = readHolds.get();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   526
                                if (rh.count == 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   527
                                    readHolds.remove();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   528
                            }
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   529
                        }
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   530
                        if (rh.count == 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   531
                            return -1;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   532
                    }
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   533
                }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   534
                if (sharedCount(c) == MAX_COUNT)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   535
                    throw new Error("Maximum lock count exceeded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   536
                if (compareAndSetState(c, c + SHARED_UNIT)) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   537
                    if (sharedCount(c) == 0) {
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   538
                        firstReader = current;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   539
                        firstReaderHoldCount = 1;
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   540
                    } else if (firstReader == current) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   541
                        firstReaderHoldCount++;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   542
                    } else {
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   543
                        if (rh == null)
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   544
                            rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   545
                        if (rh == null ||
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   546
                            rh.tid != LockSupport.getThreadId(current))
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   547
                            rh = readHolds.get();
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   548
                        else if (rh.count == 0)
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   549
                            readHolds.set(rh);
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   550
                        rh.count++;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   551
                        cachedHoldCounter = rh; // cache for release
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   552
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   553
                    return 1;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   554
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   555
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   556
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   557
90ce3da70b43 Initial load
duke
parents:
diff changeset
   558
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   559
         * Performs tryLock for write, enabling barging in both modes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   560
         * This is identical in effect to tryAcquire except for lack
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   561
         * of calls to writerShouldBlock.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   562
         */
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   563
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   564
        final boolean tryWriteLock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   565
            Thread current = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   566
            int c = getState();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   567
            if (c != 0) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   568
                int w = exclusiveCount(c);
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   569
                if (w == 0 || current != getExclusiveOwnerThread())
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   570
                    return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   571
                if (w == MAX_COUNT)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   572
                    throw new Error("Maximum lock count exceeded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   573
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   574
            if (!compareAndSetState(c, c + 1))
90ce3da70b43 Initial load
duke
parents:
diff changeset
   575
                return false;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   576
            setExclusiveOwnerThread(current);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   577
            return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   578
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   579
90ce3da70b43 Initial load
duke
parents:
diff changeset
   580
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   581
         * Performs tryLock for read, enabling barging in both modes.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   582
         * This is identical in effect to tryAcquireShared except for
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   583
         * lack of calls to readerShouldBlock.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   584
         */
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   585
        @ReservedStackAccess
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   586
        final boolean tryReadLock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   587
            Thread current = Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   588
            for (;;) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   589
                int c = getState();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   590
                if (exclusiveCount(c) != 0 &&
90ce3da70b43 Initial load
duke
parents:
diff changeset
   591
                    getExclusiveOwnerThread() != current)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   592
                    return false;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   593
                int r = sharedCount(c);
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   594
                if (r == MAX_COUNT)
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   595
                    throw new Error("Maximum lock count exceeded");
90ce3da70b43 Initial load
duke
parents:
diff changeset
   596
                if (compareAndSetState(c, c + SHARED_UNIT)) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   597
                    if (r == 0) {
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   598
                        firstReader = current;
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   599
                        firstReaderHoldCount = 1;
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   600
                    } else if (firstReader == current) {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   601
                        firstReaderHoldCount++;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   602
                    } else {
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   603
                        HoldCounter rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   604
                        if (rh == null ||
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   605
                            rh.tid != LockSupport.getThreadId(current))
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   606
                            cachedHoldCounter = rh = readHolds.get();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   607
                        else if (rh.count == 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   608
                            readHolds.set(rh);
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   609
                        rh.count++;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   610
                    }
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   611
                    return true;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   612
                }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   613
            }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   614
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   615
90ce3da70b43 Initial load
duke
parents:
diff changeset
   616
        protected final boolean isHeldExclusively() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   617
            // While we must in general read state before owner,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   618
            // we don't need to do so to check if current thread is owner
90ce3da70b43 Initial load
duke
parents:
diff changeset
   619
            return getExclusiveOwnerThread() == Thread.currentThread();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   620
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   621
90ce3da70b43 Initial load
duke
parents:
diff changeset
   622
        // Methods relayed to outer class
90ce3da70b43 Initial load
duke
parents:
diff changeset
   623
90ce3da70b43 Initial load
duke
parents:
diff changeset
   624
        final ConditionObject newCondition() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   625
            return new ConditionObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   626
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   627
90ce3da70b43 Initial load
duke
parents:
diff changeset
   628
        final Thread getOwner() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   629
            // Must read state before owner to ensure memory consistency
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   630
            return ((exclusiveCount(getState()) == 0) ?
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   631
                    null :
90ce3da70b43 Initial load
duke
parents:
diff changeset
   632
                    getExclusiveOwnerThread());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   633
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   634
90ce3da70b43 Initial load
duke
parents:
diff changeset
   635
        final int getReadLockCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   636
            return sharedCount(getState());
90ce3da70b43 Initial load
duke
parents:
diff changeset
   637
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   638
90ce3da70b43 Initial load
duke
parents:
diff changeset
   639
        final boolean isWriteLocked() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   640
            return exclusiveCount(getState()) != 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   641
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   642
90ce3da70b43 Initial load
duke
parents:
diff changeset
   643
        final int getWriteHoldCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   644
            return isHeldExclusively() ? exclusiveCount(getState()) : 0;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   645
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   646
90ce3da70b43 Initial load
duke
parents:
diff changeset
   647
        final int getReadHoldCount() {
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   648
            if (getReadLockCount() == 0)
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   649
                return 0;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   650
2431
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   651
            Thread current = Thread.currentThread();
54a65419300f 6822903: Reliability and documentation improvements for ReentrantReadWriteLock
dl
parents: 62
diff changeset
   652
            if (firstReader == current)
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   653
                return firstReaderHoldCount;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   654
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   655
            HoldCounter rh = cachedHoldCounter;
39725
9548f8d846e9 8080603: Replace Unsafe with VarHandle in java.util.concurrent classes
dl
parents: 34346
diff changeset
   656
            if (rh != null && rh.tid == LockSupport.getThreadId(current))
62
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   657
                return rh.count;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   658
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   659
            int count = readHolds.get().count;
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   660
            if (count == 0) readHolds.remove();
ea448c54b34b 6625723: Excessive ThreadLocal storage used by ReentrantReadWriteLock
martin
parents: 2
diff changeset
   661
            return count;
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   662
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   663
90ce3da70b43 Initial load
duke
parents:
diff changeset
   664
        /**
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   665
         * Reconstitutes the instance from a stream (that is, deserializes it).
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   666
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   667
        private void readObject(java.io.ObjectInputStream s)
90ce3da70b43 Initial load
duke
parents:
diff changeset
   668
            throws java.io.IOException, ClassNotFoundException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   669
            s.defaultReadObject();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   670
            readHolds = new ThreadLocalHoldCounter();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   671
            setState(0); // reset to unlocked state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   672
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   673
90ce3da70b43 Initial load
duke
parents:
diff changeset
   674
        final int getCount() { return getState(); }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   675
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   676
90ce3da70b43 Initial load
duke
parents:
diff changeset
   677
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   678
     * Nonfair version of Sync
90ce3da70b43 Initial load
duke
parents:
diff changeset
   679
     */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   680
    static final class NonfairSync extends Sync {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   681
        private static final long serialVersionUID = -8159625535654395037L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   682
        final boolean writerShouldBlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   683
            return false; // writers can always barge
90ce3da70b43 Initial load
duke
parents:
diff changeset
   684
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   685
        final boolean readerShouldBlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   686
            /* As a heuristic to avoid indefinite writer starvation,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   687
             * block if the thread that momentarily appears to be head
90ce3da70b43 Initial load
duke
parents:
diff changeset
   688
             * of queue, if one exists, is a waiting writer.  This is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   689
             * only a probabilistic effect since a new reader will not
90ce3da70b43 Initial load
duke
parents:
diff changeset
   690
             * block if there is a waiting writer behind other enabled
90ce3da70b43 Initial load
duke
parents:
diff changeset
   691
             * readers that have not yet drained from the queue.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   692
             */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   693
            return apparentlyFirstQueuedIsExclusive();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   694
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   695
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   696
90ce3da70b43 Initial load
duke
parents:
diff changeset
   697
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   698
     * Fair version of Sync
90ce3da70b43 Initial load
duke
parents:
diff changeset
   699
     */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   700
    static final class FairSync extends Sync {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   701
        private static final long serialVersionUID = -2274990926593161451L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   702
        final boolean writerShouldBlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   703
            return hasQueuedPredecessors();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   704
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   705
        final boolean readerShouldBlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   706
            return hasQueuedPredecessors();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   707
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   708
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   709
90ce3da70b43 Initial load
duke
parents:
diff changeset
   710
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   711
     * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   712
     */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   713
    public static class ReadLock implements Lock, java.io.Serializable {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   714
        private static final long serialVersionUID = -5992448646407690164L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   715
        private final Sync sync;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   716
90ce3da70b43 Initial load
duke
parents:
diff changeset
   717
        /**
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   718
         * Constructor for use by subclasses.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   719
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   720
         * @param lock the outer lock object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   721
         * @throws NullPointerException if the lock is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   722
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   723
        protected ReadLock(ReentrantReadWriteLock lock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   724
            sync = lock.sync;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   725
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   726
90ce3da70b43 Initial load
duke
parents:
diff changeset
   727
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   728
         * Acquires the read lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   729
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   730
         * <p>Acquires the read lock if the write lock is not held by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   731
         * another thread and returns immediately.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   732
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   733
         * <p>If the write lock is held by another thread then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   734
         * the current thread becomes disabled for thread scheduling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   735
         * purposes and lies dormant until the read lock has been acquired.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   736
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   737
        public void lock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   738
            sync.acquireShared(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   739
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   740
90ce3da70b43 Initial load
duke
parents:
diff changeset
   741
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   742
         * Acquires the read lock unless the current thread is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   743
         * {@linkplain Thread#interrupt interrupted}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   744
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   745
         * <p>Acquires the read lock if the write lock is not held
90ce3da70b43 Initial load
duke
parents:
diff changeset
   746
         * by another thread and returns immediately.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   747
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   748
         * <p>If the write lock is held by another thread then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   749
         * current thread becomes disabled for thread scheduling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   750
         * purposes and lies dormant until one of two things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   751
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   752
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   753
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   754
         * <li>The read lock is acquired by the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   755
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   756
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   757
         * the current thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   758
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   759
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   760
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   761
         * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   762
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   763
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   764
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   765
         * <li>has its interrupted status set on entry to this method; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   766
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   767
         * <li>is {@linkplain Thread#interrupt interrupted} while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   768
         * acquiring the read lock,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   769
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   770
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   771
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   772
         * then {@link InterruptedException} is thrown and the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   773
         * thread's interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   774
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   775
         * <p>In this implementation, as this method is an explicit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   776
         * interruption point, preference is given to responding to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   777
         * the interrupt over normal or reentrant acquisition of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   778
         * lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   779
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   780
         * @throws InterruptedException if the current thread is interrupted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   781
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   782
        public void lockInterruptibly() throws InterruptedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   783
            sync.acquireSharedInterruptibly(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   784
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   785
90ce3da70b43 Initial load
duke
parents:
diff changeset
   786
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   787
         * Acquires the read lock only if the write lock is not held by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   788
         * another thread at the time of invocation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   789
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   790
         * <p>Acquires the read lock if the write lock is not held by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   791
         * another thread and returns immediately with the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   792
         * {@code true}. Even when this lock has been set to use a
90ce3da70b43 Initial load
duke
parents:
diff changeset
   793
         * fair ordering policy, a call to {@code tryLock()}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   794
         * <em>will</em> immediately acquire the read lock if it is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   795
         * available, whether or not other threads are currently
90ce3da70b43 Initial load
duke
parents:
diff changeset
   796
         * waiting for the read lock.  This &quot;barging&quot; behavior
90ce3da70b43 Initial load
duke
parents:
diff changeset
   797
         * can be useful in certain circumstances, even though it
90ce3da70b43 Initial load
duke
parents:
diff changeset
   798
         * breaks fairness. If you want to honor the fairness setting
90ce3da70b43 Initial load
duke
parents:
diff changeset
   799
         * for this lock, then use {@link #tryLock(long, TimeUnit)
45937
646816090183 8178409: Miscellaneous changes imported from jsr166 CVS 2017-07
dl
parents: 44589
diff changeset
   800
         * tryLock(0, TimeUnit.SECONDS)} which is almost equivalent
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   801
         * (it also detects interruption).
90ce3da70b43 Initial load
duke
parents:
diff changeset
   802
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   803
         * <p>If the write lock is held by another thread then
90ce3da70b43 Initial load
duke
parents:
diff changeset
   804
         * this method will return immediately with the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   805
         * {@code false}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   806
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   807
         * @return {@code true} if the read lock was acquired
90ce3da70b43 Initial load
duke
parents:
diff changeset
   808
         */
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   809
        public boolean tryLock() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   810
            return sync.tryReadLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   811
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   812
90ce3da70b43 Initial load
duke
parents:
diff changeset
   813
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   814
         * Acquires the read lock if the write lock is not held by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   815
         * another thread within the given waiting time and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   816
         * current thread has not been {@linkplain Thread#interrupt
90ce3da70b43 Initial load
duke
parents:
diff changeset
   817
         * interrupted}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   818
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   819
         * <p>Acquires the read lock if the write lock is not held by
90ce3da70b43 Initial load
duke
parents:
diff changeset
   820
         * another thread and returns immediately with the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   821
         * {@code true}. If this lock has been set to use a fair
90ce3da70b43 Initial load
duke
parents:
diff changeset
   822
         * ordering policy then an available lock <em>will not</em> be
90ce3da70b43 Initial load
duke
parents:
diff changeset
   823
         * acquired if any other threads are waiting for the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   824
         * lock. This is in contrast to the {@link #tryLock()}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   825
         * method. If you want a timed {@code tryLock} that does
90ce3da70b43 Initial load
duke
parents:
diff changeset
   826
         * permit barging on a fair lock then combine the timed and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   827
         * un-timed forms together:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   828
         *
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   829
         * <pre> {@code
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   830
         * if (lock.tryLock() ||
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   831
         *     lock.tryLock(timeout, unit)) {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   832
         *   ...
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   833
         * }}</pre>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   834
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   835
         * <p>If the write lock is held by another thread then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   836
         * current thread becomes disabled for thread scheduling
90ce3da70b43 Initial load
duke
parents:
diff changeset
   837
         * purposes and lies dormant until one of three things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   838
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   839
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   840
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   841
         * <li>The read lock is acquired by the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   842
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   843
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   844
         * the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   845
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   846
         * <li>The specified waiting time elapses.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   847
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   848
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   849
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   850
         * <p>If the read lock is acquired then the value {@code true} is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   851
         * returned.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   852
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   853
         * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   854
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   855
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   856
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   857
         * <li>has its interrupted status set on entry to this method; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   858
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   859
         * <li>is {@linkplain Thread#interrupt interrupted} while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   860
         * acquiring the read lock,
90ce3da70b43 Initial load
duke
parents:
diff changeset
   861
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   862
         * </ul> then {@link InterruptedException} is thrown and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   863
         * current thread's interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   864
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   865
         * <p>If the specified waiting time elapses then the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
   866
         * {@code false} is returned.  If the time is less than or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   867
         * equal to zero, the method will not wait at all.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   868
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   869
         * <p>In this implementation, as this method is an explicit
90ce3da70b43 Initial load
duke
parents:
diff changeset
   870
         * interruption point, preference is given to responding to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   871
         * the interrupt over normal or reentrant acquisition of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   872
         * lock, and over reporting the elapse of the waiting time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   873
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   874
         * @param timeout the time to wait for the read lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   875
         * @param unit the time unit of the timeout argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
   876
         * @return {@code true} if the read lock was acquired
90ce3da70b43 Initial load
duke
parents:
diff changeset
   877
         * @throws InterruptedException if the current thread is interrupted
90ce3da70b43 Initial load
duke
parents:
diff changeset
   878
         * @throws NullPointerException if the time unit is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   879
         */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   880
        public boolean tryLock(long timeout, TimeUnit unit)
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   881
                throws InterruptedException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   882
            return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
90ce3da70b43 Initial load
duke
parents:
diff changeset
   883
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   884
90ce3da70b43 Initial load
duke
parents:
diff changeset
   885
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   886
         * Attempts to release this lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   887
         *
18575
2ab0d0b3ecad 8017739: ReentrantReadWriteLock is confused by the Threads with reused IDs
dl
parents: 14325
diff changeset
   888
         * <p>If the number of readers is now zero then the lock
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   889
         * is made available for write lock attempts. If the current
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   890
         * thread does not hold this lock then {@link
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   891
         * IllegalMonitorStateException} is thrown.
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   892
         *
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   893
         * @throws IllegalMonitorStateException if the current thread
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   894
         * does not hold this lock
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   895
         */
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
   896
        public void unlock() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   897
            sync.releaseShared(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   898
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   899
90ce3da70b43 Initial load
duke
parents:
diff changeset
   900
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   901
         * Throws {@code UnsupportedOperationException} because
90ce3da70b43 Initial load
duke
parents:
diff changeset
   902
         * {@code ReadLocks} do not support conditions.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   903
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   904
         * @throws UnsupportedOperationException always
90ce3da70b43 Initial load
duke
parents:
diff changeset
   905
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   906
        public Condition newCondition() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   907
            throw new UnsupportedOperationException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   908
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   909
90ce3da70b43 Initial load
duke
parents:
diff changeset
   910
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   911
         * Returns a string identifying this lock, as well as its lock state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   912
         * The state, in brackets, includes the String {@code "Read locks ="}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   913
         * followed by the number of held read locks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   914
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   915
         * @return a string identifying this lock, as well as its lock state
90ce3da70b43 Initial load
duke
parents:
diff changeset
   916
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   917
        public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   918
            int r = sync.getReadLockCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
   919
            return super.toString() +
90ce3da70b43 Initial load
duke
parents:
diff changeset
   920
                "[Read locks = " + r + "]";
90ce3da70b43 Initial load
duke
parents:
diff changeset
   921
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   922
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   923
90ce3da70b43 Initial load
duke
parents:
diff changeset
   924
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   925
     * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   926
     */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
   927
    public static class WriteLock implements Lock, java.io.Serializable {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   928
        private static final long serialVersionUID = -4992448646407690164L;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   929
        private final Sync sync;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   930
90ce3da70b43 Initial load
duke
parents:
diff changeset
   931
        /**
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
   932
         * Constructor for use by subclasses.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
   933
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   934
         * @param lock the outer lock object
90ce3da70b43 Initial load
duke
parents:
diff changeset
   935
         * @throws NullPointerException if the lock is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
   936
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   937
        protected WriteLock(ReentrantReadWriteLock lock) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   938
            sync = lock.sync;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   939
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   940
90ce3da70b43 Initial load
duke
parents:
diff changeset
   941
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   942
         * Acquires the write lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   943
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   944
         * <p>Acquires the write lock if neither the read nor write lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   945
         * are held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   946
         * and returns immediately, setting the write lock hold count to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   947
         * one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   948
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   949
         * <p>If the current thread already holds the write lock then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   950
         * hold count is incremented by one and the method returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   951
         * immediately.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   952
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   953
         * <p>If the lock is held by another thread then the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   954
         * thread becomes disabled for thread scheduling purposes and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   955
         * lies dormant until the write lock has been acquired, at which
90ce3da70b43 Initial load
duke
parents:
diff changeset
   956
         * time the write lock hold count is set to one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   957
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
   958
        public void lock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
   959
            sync.acquire(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
   960
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
   961
90ce3da70b43 Initial load
duke
parents:
diff changeset
   962
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
   963
         * Acquires the write lock unless the current thread is
90ce3da70b43 Initial load
duke
parents:
diff changeset
   964
         * {@linkplain Thread#interrupt interrupted}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   965
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   966
         * <p>Acquires the write lock if neither the read nor write lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
   967
         * are held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
   968
         * and returns immediately, setting the write lock hold count to
90ce3da70b43 Initial load
duke
parents:
diff changeset
   969
         * one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   970
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   971
         * <p>If the current thread already holds this lock then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   972
         * hold count is incremented by one and the method returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
   973
         * immediately.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   974
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   975
         * <p>If the lock is held by another thread then the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
   976
         * thread becomes disabled for thread scheduling purposes and
90ce3da70b43 Initial load
duke
parents:
diff changeset
   977
         * lies dormant until one of two things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   978
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   979
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   980
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   981
         * <li>The write lock is acquired by the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   982
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   983
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
90ce3da70b43 Initial load
duke
parents:
diff changeset
   984
         * the current thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   985
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   986
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   987
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   988
         * <p>If the write lock is acquired by the current thread then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
   989
         * lock hold count is set to one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
   990
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   991
         * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
   992
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   993
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
   994
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   995
         * <li>has its interrupted status set on entry to this method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
   996
         * or
90ce3da70b43 Initial load
duke
parents:
diff changeset
   997
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
   998
         * <li>is {@linkplain Thread#interrupt interrupted} while
90ce3da70b43 Initial load
duke
parents:
diff changeset
   999
         * acquiring the write lock,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1000
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1001
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1002
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1003
         * then {@link InterruptedException} is thrown and the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1004
         * thread's interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1005
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1006
         * <p>In this implementation, as this method is an explicit
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1007
         * interruption point, preference is given to responding to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1008
         * the interrupt over normal or reentrant acquisition of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1009
         * lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1010
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1011
         * @throws InterruptedException if the current thread is interrupted
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1012
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1013
        public void lockInterruptibly() throws InterruptedException {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1014
            sync.acquireInterruptibly(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1015
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1016
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1017
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1018
         * Acquires the write lock only if it is not held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1019
         * at the time of invocation.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1020
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1021
         * <p>Acquires the write lock if neither the read nor write lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1022
         * are held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1023
         * and returns immediately with the value {@code true},
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1024
         * setting the write lock hold count to one. Even when this lock has
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1025
         * been set to use a fair ordering policy, a call to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1026
         * {@code tryLock()} <em>will</em> immediately acquire the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1027
         * lock if it is available, whether or not other threads are
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1028
         * currently waiting for the write lock.  This &quot;barging&quot;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1029
         * behavior can be useful in certain circumstances, even
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1030
         * though it breaks fairness. If you want to honor the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1031
         * fairness setting for this lock, then use {@link
45937
646816090183 8178409: Miscellaneous changes imported from jsr166 CVS 2017-07
dl
parents: 44589
diff changeset
  1032
         * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS)}
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1033
         * which is almost equivalent (it also detects interruption).
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1034
         *
18575
2ab0d0b3ecad 8017739: ReentrantReadWriteLock is confused by the Threads with reused IDs
dl
parents: 14325
diff changeset
  1035
         * <p>If the current thread already holds this lock then the
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1036
         * hold count is incremented by one and the method returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1037
         * {@code true}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1038
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1039
         * <p>If the lock is held by another thread then this method
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1040
         * will return immediately with the value {@code false}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1041
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1042
         * @return {@code true} if the lock was free and was acquired
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1043
         * by the current thread, or the write lock was already held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1044
         * by the current thread; and {@code false} otherwise.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1045
         */
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
  1046
        public boolean tryLock() {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1047
            return sync.tryWriteLock();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1048
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1049
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1050
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1051
         * Acquires the write lock if it is not held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1052
         * within the given waiting time and the current thread has
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1053
         * not been {@linkplain Thread#interrupt interrupted}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1054
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1055
         * <p>Acquires the write lock if neither the read nor write lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1056
         * are held by another thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1057
         * and returns immediately with the value {@code true},
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1058
         * setting the write lock hold count to one. If this lock has been
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1059
         * set to use a fair ordering policy then an available lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1060
         * <em>will not</em> be acquired if any other threads are
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1061
         * waiting for the write lock. This is in contrast to the {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1062
         * #tryLock()} method. If you want a timed {@code tryLock}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1063
         * that does permit barging on a fair lock then combine the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1064
         * timed and un-timed forms together:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1065
         *
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
  1066
         * <pre> {@code
14325
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
  1067
         * if (lock.tryLock() ||
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
  1068
         *     lock.tryLock(timeout, unit)) {
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
  1069
         *   ...
622c473a21aa 8001575: Minor/sync/cleanup j.u.c with Dougs CVS - Oct 2012
dl
parents: 9242
diff changeset
  1070
         * }}</pre>
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1071
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1072
         * <p>If the current thread already holds this lock then the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1073
         * hold count is incremented by one and the method returns
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1074
         * {@code true}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1075
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1076
         * <p>If the lock is held by another thread then the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1077
         * thread becomes disabled for thread scheduling purposes and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1078
         * lies dormant until one of three things happens:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1079
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1080
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1081
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1082
         * <li>The write lock is acquired by the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1083
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1084
         * <li>Some other thread {@linkplain Thread#interrupt interrupts}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1085
         * the current thread; or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1086
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1087
         * <li>The specified waiting time elapses
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1088
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1089
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1090
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1091
         * <p>If the write lock is acquired then the value {@code true} is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1092
         * returned and the write lock hold count is set to one.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1093
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1094
         * <p>If the current thread:
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1095
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1096
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1097
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1098
         * <li>has its interrupted status set on entry to this method;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1099
         * or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1100
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1101
         * <li>is {@linkplain Thread#interrupt interrupted} while
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1102
         * acquiring the write lock,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1103
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1104
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1105
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1106
         * then {@link InterruptedException} is thrown and the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1107
         * thread's interrupted status is cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1108
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1109
         * <p>If the specified waiting time elapses then the value
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1110
         * {@code false} is returned.  If the time is less than or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1111
         * equal to zero, the method will not wait at all.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1112
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1113
         * <p>In this implementation, as this method is an explicit
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1114
         * interruption point, preference is given to responding to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1115
         * the interrupt over normal or reentrant acquisition of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1116
         * lock, and over reporting the elapse of the waiting time.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1117
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1118
         * @param timeout the time to wait for the write lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1119
         * @param unit the time unit of the timeout argument
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1120
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1121
         * @return {@code true} if the lock was free and was acquired
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1122
         * by the current thread, or the write lock was already held by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1123
         * current thread; and {@code false} if the waiting time
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1124
         * elapsed before the lock could be acquired.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1125
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1126
         * @throws InterruptedException if the current thread is interrupted
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1127
         * @throws NullPointerException if the time unit is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1128
         */
7518
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
  1129
        public boolean tryLock(long timeout, TimeUnit unit)
0282db800fe1 7003745: Code style cleanups (sync from Dougs CVS)
dl
parents: 5506
diff changeset
  1130
                throws InterruptedException {
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1131
            return sync.tryAcquireNanos(1, unit.toNanos(timeout));
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1132
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1133
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1134
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1135
         * Attempts to release this lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1136
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1137
         * <p>If the current thread is the holder of this lock then
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1138
         * the hold count is decremented. If the hold count is now
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1139
         * zero then the lock is released.  If the current thread is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1140
         * not the holder of this lock then {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1141
         * IllegalMonitorStateException} is thrown.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1142
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1143
         * @throws IllegalMonitorStateException if the current thread does not
18575
2ab0d0b3ecad 8017739: ReentrantReadWriteLock is confused by the Threads with reused IDs
dl
parents: 14325
diff changeset
  1144
         * hold this lock
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1145
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1146
        public void unlock() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1147
            sync.release(1);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1148
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1149
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1150
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1151
         * Returns a {@link Condition} instance for use with this
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1152
         * {@link Lock} instance.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1153
         * <p>The returned {@link Condition} instance supports the same
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1154
         * usages as do the {@link Object} monitor methods ({@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1155
         * Object#wait() wait}, {@link Object#notify notify}, and {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1156
         * Object#notifyAll notifyAll}) when used with the built-in
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1157
         * monitor lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1158
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1159
         * <ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1160
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1161
         * <li>If this write lock is not held when any {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1162
         * Condition} method is called then an {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1163
         * IllegalMonitorStateException} is thrown.  (Read locks are
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1164
         * held independently of write locks, so are not checked or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1165
         * affected. However it is essentially always an error to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1166
         * invoke a condition waiting method when the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1167
         * has also acquired read locks, since other threads that
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1168
         * could unblock it will not be able to acquire the write
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1169
         * lock.)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1170
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1171
         * <li>When the condition {@linkplain Condition#await() waiting}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1172
         * methods are called the write lock is released and, before
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1173
         * they return, the write lock is reacquired and the lock hold
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1174
         * count restored to what it was when the method was called.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1175
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1176
         * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1177
         * waiting then the wait will terminate, an {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1178
         * InterruptedException} will be thrown, and the thread's
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1179
         * interrupted status will be cleared.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1180
         *
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
  1181
         * <li>Waiting threads are signalled in FIFO order.
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1182
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1183
         * <li>The ordering of lock reacquisition for threads returning
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1184
         * from waiting methods is the same as for threads initially
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1185
         * acquiring the lock, which is in the default case not specified,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1186
         * but for <em>fair</em> locks favors those threads that have been
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1187
         * waiting the longest.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1188
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1189
         * </ul>
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1190
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1191
         * @return the Condition object
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1192
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1193
        public Condition newCondition() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1194
            return sync.newCondition();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1195
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1196
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1197
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1198
         * Returns a string identifying this lock, as well as its lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1199
         * state.  The state, in brackets includes either the String
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1200
         * {@code "Unlocked"} or the String {@code "Locked by"}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1201
         * followed by the {@linkplain Thread#getName name} of the owning thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1202
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1203
         * @return a string identifying this lock, as well as its lock state
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1204
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1205
        public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1206
            Thread o = sync.getOwner();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1207
            return super.toString() + ((o == null) ?
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1208
                                       "[Unlocked]" :
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1209
                                       "[Locked by thread " + o.getName() + "]");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1210
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1211
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1212
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1213
         * Queries if this write lock is held by the current thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1214
         * Identical in effect to {@link
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1215
         * ReentrantReadWriteLock#isWriteLockedByCurrentThread}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1216
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1217
         * @return {@code true} if the current thread holds this lock and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1218
         *         {@code false} otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1219
         * @since 1.6
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1220
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1221
        public boolean isHeldByCurrentThread() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1222
            return sync.isHeldExclusively();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1223
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1224
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1225
        /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1226
         * Queries the number of holds on this write lock by the current
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1227
         * thread.  A thread has a hold on a lock for each lock action
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1228
         * that is not matched by an unlock action.  Identical in effect
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1229
         * to {@link ReentrantReadWriteLock#getWriteHoldCount}.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1230
         *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1231
         * @return the number of holds on this lock by the current thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1232
         *         or zero if this lock is not held by the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1233
         * @since 1.6
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1234
         */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1235
        public int getHoldCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1236
            return sync.getWriteHoldCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1237
        }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1238
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1239
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1240
    // Instrumentation and status
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1241
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1242
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1243
     * Returns {@code true} if this lock has fairness set true.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1244
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1245
     * @return {@code true} if this lock has fairness set true
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1246
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1247
    public final boolean isFair() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1248
        return sync instanceof FairSync;
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1249
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1250
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1251
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1252
     * Returns the thread that currently owns the write lock, or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1253
     * {@code null} if not owned. When this method is called by a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1254
     * thread that is not the owner, the return value reflects a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1255
     * best-effort approximation of current lock status. For example,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1256
     * the owner may be momentarily {@code null} even if there are
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1257
     * threads trying to acquire the lock but have not yet done so.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1258
     * This method is designed to facilitate construction of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1259
     * subclasses that provide more extensive lock monitoring
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1260
     * facilities.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1261
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1262
     * @return the owner, or {@code null} if not owned
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1263
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1264
    protected Thread getOwner() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1265
        return sync.getOwner();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1266
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1267
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1268
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1269
     * Queries the number of read locks held for this lock. This
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1270
     * method is designed for use in monitoring system state, not for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1271
     * synchronization control.
18575
2ab0d0b3ecad 8017739: ReentrantReadWriteLock is confused by the Threads with reused IDs
dl
parents: 14325
diff changeset
  1272
     * @return the number of read locks held
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1273
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1274
    public int getReadLockCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1275
        return sync.getReadLockCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1276
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1277
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1278
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1279
     * Queries if the write lock is held by any thread. This method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1280
     * designed for use in monitoring system state, not for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1281
     * synchronization control.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1282
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1283
     * @return {@code true} if any thread holds the write lock and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1284
     *         {@code false} otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1285
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1286
    public boolean isWriteLocked() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1287
        return sync.isWriteLocked();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1288
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1289
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1290
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1291
     * Queries if the write lock is held by the current thread.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1292
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1293
     * @return {@code true} if the current thread holds the write lock and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1294
     *         {@code false} otherwise
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1295
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1296
    public boolean isWriteLockedByCurrentThread() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1297
        return sync.isHeldExclusively();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1298
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1299
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1300
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1301
     * Queries the number of reentrant write holds on this lock by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1302
     * current thread.  A writer thread has a hold on a lock for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1303
     * each lock action that is not matched by an unlock action.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1304
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1305
     * @return the number of holds on the write lock by the current thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1306
     *         or zero if the write lock is not held by the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1307
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1308
    public int getWriteHoldCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1309
        return sync.getWriteHoldCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1310
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1311
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1312
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1313
     * Queries the number of reentrant read holds on this lock by the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1314
     * current thread.  A reader thread has a hold on a lock for
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1315
     * each lock action that is not matched by an unlock action.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1316
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1317
     * @return the number of holds on the read lock by the current thread,
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1318
     *         or zero if the read lock is not held by the current thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1319
     * @since 1.6
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1320
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1321
    public int getReadHoldCount() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1322
        return sync.getReadHoldCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1323
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1324
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1325
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1326
     * Returns a collection containing threads that may be waiting to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1327
     * acquire the write lock.  Because the actual set of threads may
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1328
     * change dynamically while constructing this result, the returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1329
     * collection is only a best-effort estimate.  The elements of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1330
     * returned collection are in no particular order.  This method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1331
     * designed to facilitate construction of subclasses that provide
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1332
     * more extensive lock monitoring facilities.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1333
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1334
     * @return the collection of threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1335
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1336
    protected Collection<Thread> getQueuedWriterThreads() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1337
        return sync.getExclusiveQueuedThreads();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1338
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1339
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1340
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1341
     * Returns a collection containing threads that may be waiting to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1342
     * acquire the read lock.  Because the actual set of threads may
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1343
     * change dynamically while constructing this result, the returned
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1344
     * collection is only a best-effort estimate.  The elements of the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1345
     * returned collection are in no particular order.  This method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1346
     * designed to facilitate construction of subclasses that provide
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1347
     * more extensive lock monitoring facilities.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1348
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1349
     * @return the collection of threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1350
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1351
    protected Collection<Thread> getQueuedReaderThreads() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1352
        return sync.getSharedQueuedThreads();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1353
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1354
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1355
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1356
     * Queries whether any threads are waiting to acquire the read or
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1357
     * write lock. Note that because cancellations may occur at any
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1358
     * time, a {@code true} return does not guarantee that any other
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1359
     * thread will ever acquire a lock.  This method is designed
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1360
     * primarily for use in monitoring of the system state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1361
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1362
     * @return {@code true} if there may be other threads waiting to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1363
     *         acquire the lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1364
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1365
    public final boolean hasQueuedThreads() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1366
        return sync.hasQueuedThreads();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1367
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1368
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1369
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1370
     * Queries whether the given thread is waiting to acquire either
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1371
     * the read or write lock. Note that because cancellations may
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1372
     * occur at any time, a {@code true} return does not guarantee
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1373
     * that this thread will ever acquire a lock.  This method is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1374
     * designed primarily for use in monitoring of the system state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1375
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1376
     * @param thread the thread
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1377
     * @return {@code true} if the given thread is queued waiting for this lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1378
     * @throws NullPointerException if the thread is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1379
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1380
    public final boolean hasQueuedThread(Thread thread) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1381
        return sync.isQueued(thread);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1382
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1383
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1384
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1385
     * Returns an estimate of the number of threads waiting to acquire
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1386
     * either the read or write lock.  The value is only an estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1387
     * because the number of threads may change dynamically while this
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1388
     * method traverses internal data structures.  This method is
32990
299a81977f48 8134855: Bulk integration of java.util.concurrent.locks classes
dl
parents: 25859
diff changeset
  1389
     * designed for use in monitoring system state, not for
2
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1390
     * synchronization control.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1391
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1392
     * @return the estimated number of threads waiting for this lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1393
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1394
    public final int getQueueLength() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1395
        return sync.getQueueLength();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1396
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1397
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1398
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1399
     * Returns a collection containing threads that may be waiting to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1400
     * acquire either the read or write lock.  Because the actual set
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1401
     * of threads may change dynamically while constructing this
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1402
     * result, the returned collection is only a best-effort estimate.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1403
     * The elements of the returned collection are in no particular
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1404
     * order.  This method is designed to facilitate construction of
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1405
     * subclasses that provide more extensive monitoring facilities.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1406
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1407
     * @return the collection of threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1408
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1409
    protected Collection<Thread> getQueuedThreads() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1410
        return sync.getQueuedThreads();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1411
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1412
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1413
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1414
     * Queries whether any threads are waiting on the given condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1415
     * associated with the write lock. Note that because timeouts and
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1416
     * interrupts may occur at any time, a {@code true} return does
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1417
     * not guarantee that a future {@code signal} will awaken any
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1418
     * threads.  This method is designed primarily for use in
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1419
     * monitoring of the system state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1420
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1421
     * @param condition the condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1422
     * @return {@code true} if there are any waiting threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1423
     * @throws IllegalMonitorStateException if this lock is not held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1424
     * @throws IllegalArgumentException if the given condition is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1425
     *         not associated with this lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1426
     * @throws NullPointerException if the condition is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1427
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1428
    public boolean hasWaiters(Condition condition) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1429
        if (condition == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1430
            throw new NullPointerException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1431
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1432
            throw new IllegalArgumentException("not owner");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1433
        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject)condition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1434
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1435
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1436
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1437
     * Returns an estimate of the number of threads waiting on the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1438
     * given condition associated with the write lock. Note that because
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1439
     * timeouts and interrupts may occur at any time, the estimate
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1440
     * serves only as an upper bound on the actual number of waiters.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1441
     * This method is designed for use in monitoring of the system
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1442
     * state, not for synchronization control.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1443
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1444
     * @param condition the condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1445
     * @return the estimated number of waiting threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1446
     * @throws IllegalMonitorStateException if this lock is not held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1447
     * @throws IllegalArgumentException if the given condition is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1448
     *         not associated with this lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1449
     * @throws NullPointerException if the condition is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1450
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1451
    public int getWaitQueueLength(Condition condition) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1452
        if (condition == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1453
            throw new NullPointerException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1454
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1455
            throw new IllegalArgumentException("not owner");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1456
        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject)condition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1457
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1458
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1459
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1460
     * Returns a collection containing those threads that may be
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1461
     * waiting on the given condition associated with the write lock.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1462
     * Because the actual set of threads may change dynamically while
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1463
     * constructing this result, the returned collection is only a
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1464
     * best-effort estimate. The elements of the returned collection
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1465
     * are in no particular order.  This method is designed to
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1466
     * facilitate construction of subclasses that provide more
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1467
     * extensive condition monitoring facilities.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1468
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1469
     * @param condition the condition
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1470
     * @return the collection of threads
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1471
     * @throws IllegalMonitorStateException if this lock is not held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1472
     * @throws IllegalArgumentException if the given condition is
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1473
     *         not associated with this lock
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1474
     * @throws NullPointerException if the condition is null
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1475
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1476
    protected Collection<Thread> getWaitingThreads(Condition condition) {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1477
        if (condition == null)
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1478
            throw new NullPointerException();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1479
        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1480
            throw new IllegalArgumentException("not owner");
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1481
        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject)condition);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1482
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1483
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1484
    /**
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1485
     * Returns a string identifying this lock, as well as its lock state.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1486
     * The state, in brackets, includes the String {@code "Write locks ="}
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1487
     * followed by the number of reentrantly held write locks, and the
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1488
     * String {@code "Read locks ="} followed by the number of held
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1489
     * read locks.
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1490
     *
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1491
     * @return a string identifying this lock, as well as its lock state
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1492
     */
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1493
    public String toString() {
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1494
        int c = sync.getCount();
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1495
        int w = Sync.exclusiveCount(c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1496
        int r = Sync.sharedCount(c);
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1497
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1498
        return super.toString() +
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1499
            "[Write locks = " + w + ", Read locks = " + r + "]";
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1500
    }
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1501
90ce3da70b43 Initial load
duke
parents:
diff changeset
  1502
}