• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /**
5  *******************************************************************************
6  * Copyright (C) 2001-2013, International Business Machines Corporation and    *
7  * others. All Rights Reserved.                                                *
8  *******************************************************************************
9  */
10 package android.icu.impl;
11 
12 import java.util.concurrent.locks.ReentrantReadWriteLock;
13 
14 
15 /**
16  * <p>A Reader/Writer lock originally written for ICU service
17  * implementation. The internal implementation was replaced
18  * with the JDK's stock read write lock (ReentrantReadWriteLock)
19  * for ICU 52.</p>
20  *
21  * <p>This assumes that there will be little writing contention.
22  * It also doesn't allow active readers to acquire and release
23  * a write lock, or deal with priority inversion issues.</p>
24  *
25  * <p>Access to the lock should be enclosed in a try/finally block
26  * in order to ensure that the lock is always released in case of
27  * exceptions:<br><pre>
28  * try {
29  *     lock.acquireRead();
30  *     // use service protected by the lock
31  * }
32  * finally {
33  *     lock.releaseRead();
34  * }
35  * </pre></p>
36  *
37  * <p>The lock provides utility methods getStats and clearStats
38  * to return statistics on the use of the lock.</p>
39  * @hide Only a subset of ICU is exposed in Android
40  */
41 public class ICURWLock {
42     private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
43 
44     private Stats stats = null;
45 
46     /**
47      * Internal class used to gather statistics on the RWLock.
48      */
49     public final static class Stats {
50         /**
51          * Number of times read access granted (read count).
52          */
53         public int _rc;
54 
55         /**
56          * Number of times concurrent read access granted (multiple read count).
57          */
58         public int _mrc;
59 
60         /**
61          * Number of times blocked for read (waiting reader count).
62          */
63         public int _wrc; // wait for read
64 
65         /**
66          * Number of times write access granted (writer count).
67          */
68         public int _wc;
69 
70         /**
71          * Number of times blocked for write (waiting writer count).
72          */
73         public int _wwc;
74 
Stats()75         private Stats() {
76         }
77 
Stats(int rc, int mrc, int wrc, int wc, int wwc)78         private Stats(int rc, int mrc, int wrc, int wc, int wwc) {
79             this._rc = rc;
80             this._mrc = mrc;
81             this._wrc = wrc;
82             this._wc = wc;
83             this._wwc = wwc;
84         }
85 
Stats(Stats rhs)86         private Stats(Stats rhs) {
87             this(rhs._rc, rhs._mrc, rhs._wrc, rhs._wc, rhs._wwc);
88         }
89 
90         /**
91          * Return a string listing all the stats.
92          */
93         @Override
toString()94         public String toString() {
95             return " rc: " + _rc +
96                 " mrc: " + _mrc +
97                 " wrc: " + _wrc +
98                 " wc: " + _wc +
99                 " wwc: " + _wwc;
100         }
101     }
102 
103     /**
104      * Reset the stats.  Returns existing stats, if any.
105      */
resetStats()106     public synchronized Stats resetStats() {
107         Stats result = stats;
108         stats = new Stats();
109         return result;
110     }
111 
112     /**
113      * Clear the stats (stop collecting stats).  Returns existing stats, if any.
114      */
clearStats()115     public synchronized Stats clearStats() {
116         Stats result = stats;
117         stats = null;
118         return result;
119     }
120 
121     /**
122      * Return a snapshot of the current stats.  This does not reset the stats.
123      */
getStats()124     public synchronized Stats getStats() {
125         return stats == null ? null : new Stats(stats);
126     }
127 
128     /**
129      * <p>Acquire a read lock, blocking until a read lock is
130      * available.  Multiple readers can concurrently hold the read
131      * lock.</p>
132      *
133      * <p>If there's a writer, or a waiting writer, increment the
134      * waiting reader count and block on this.  Otherwise
135      * increment the active reader count and return.  Caller must call
136      * releaseRead when done (for example, in a finally block).</p>
137      */
acquireRead()138     public void acquireRead() {
139         if (stats != null) {    // stats is null by default
140             synchronized (this) {
141                 stats._rc++;
142                 if (rwl.getReadLockCount() > 0) {
143                     stats._mrc++;
144                 }
145                 if (rwl.isWriteLocked()) {
146                     stats._wrc++;
147                 }
148             }
149         }
150         rwl.readLock().lock();
151     }
152 
153     /**
154      * <p>Release a read lock and return.  An error will be thrown
155      * if a read lock is not currently held.</p>
156      *
157      * <p>If this is the last active reader, notify the oldest
158      * waiting writer.  Call when finished with work
159      * controlled by acquireRead.</p>
160      */
releaseRead()161     public void releaseRead() {
162         rwl.readLock().unlock();
163     }
164 
165     /**
166      * <p>Acquire the write lock, blocking until the write lock is
167      * available.  Only one writer can acquire the write lock, and
168      * when held, no readers can acquire the read lock.</p>
169      *
170      * <p>If there are no readers and no waiting writers, mark as
171      * having an active writer and return.  Otherwise, add a lock to the
172      * end of the waiting writer list, and block on it.  Caller
173      * must call releaseWrite when done (for example, in a finally
174      * block).<p>
175      */
acquireWrite()176     public void acquireWrite() {
177         if (stats != null) {    // stats is null by default
178             synchronized (this) {
179                 stats._wc++;
180                 if (rwl.getReadLockCount() > 0 || rwl.isWriteLocked()) {
181                     stats._wwc++;
182                 }
183             }
184         }
185         rwl.writeLock().lock();
186     }
187 
188     /**
189      * <p>Release the write lock and return.  An error will be thrown
190      * if the write lock is not currently held.</p>
191      *
192      * <p>If there are waiting readers, make them all active and
193      * notify all of them.  Otherwise, notify the oldest waiting
194      * writer, if any.  Call when finished with work controlled by
195      * acquireWrite.</p>
196      */
releaseWrite()197     public void releaseWrite() {
198         rwl.writeLock().unlock();
199     }
200 }
201