• 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 ohos.global.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 exposed on OHOS
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      * @hide exposed on OHOS
49      */
50     public final static class Stats {
51         /**
52          * Number of times read access granted (read count).
53          */
54         public int _rc;
55 
56         /**
57          * Number of times concurrent read access granted (multiple read count).
58          */
59         public int _mrc;
60 
61         /**
62          * Number of times blocked for read (waiting reader count).
63          */
64         public int _wrc; // wait for read
65 
66         /**
67          * Number of times write access granted (writer count).
68          */
69         public int _wc;
70 
71         /**
72          * Number of times blocked for write (waiting writer count).
73          */
74         public int _wwc;
75 
Stats()76         private Stats() {
77         }
78 
Stats(int rc, int mrc, int wrc, int wc, int wwc)79         private Stats(int rc, int mrc, int wrc, int wc, int wwc) {
80             this._rc = rc;
81             this._mrc = mrc;
82             this._wrc = wrc;
83             this._wc = wc;
84             this._wwc = wwc;
85         }
86 
Stats(Stats rhs)87         private Stats(Stats rhs) {
88             this(rhs._rc, rhs._mrc, rhs._wrc, rhs._wc, rhs._wwc);
89         }
90 
91         /**
92          * Return a string listing all the stats.
93          */
94         @Override
toString()95         public String toString() {
96             return " rc: " + _rc +
97                 " mrc: " + _mrc +
98                 " wrc: " + _wrc +
99                 " wc: " + _wc +
100                 " wwc: " + _wwc;
101         }
102     }
103 
104     /**
105      * Reset the stats.  Returns existing stats, if any.
106      */
resetStats()107     public synchronized Stats resetStats() {
108         Stats result = stats;
109         stats = new Stats();
110         return result;
111     }
112 
113     /**
114      * Clear the stats (stop collecting stats).  Returns existing stats, if any.
115      */
clearStats()116     public synchronized Stats clearStats() {
117         Stats result = stats;
118         stats = null;
119         return result;
120     }
121 
122     /**
123      * Return a snapshot of the current stats.  This does not reset the stats.
124      */
getStats()125     public synchronized Stats getStats() {
126         return stats == null ? null : new Stats(stats);
127     }
128 
129     /**
130      * <p>Acquire a read lock, blocking until a read lock is
131      * available.  Multiple readers can concurrently hold the read
132      * lock.</p>
133      *
134      * <p>If there's a writer, or a waiting writer, increment the
135      * waiting reader count and block on this.  Otherwise
136      * increment the active reader count and return.  Caller must call
137      * releaseRead when done (for example, in a finally block).</p>
138      */
acquireRead()139     public void acquireRead() {
140         if (stats != null) {    // stats is null by default
141             synchronized (this) {
142                 stats._rc++;
143                 if (rwl.getReadLockCount() > 0) {
144                     stats._mrc++;
145                 }
146                 if (rwl.isWriteLocked()) {
147                     stats._wrc++;
148                 }
149             }
150         }
151         rwl.readLock().lock();
152     }
153 
154     /**
155      * <p>Release a read lock and return.  An error will be thrown
156      * if a read lock is not currently held.</p>
157      *
158      * <p>If this is the last active reader, notify the oldest
159      * waiting writer.  Call when finished with work
160      * controlled by acquireRead.</p>
161      */
releaseRead()162     public void releaseRead() {
163         rwl.readLock().unlock();
164     }
165 
166     /**
167      * <p>Acquire the write lock, blocking until the write lock is
168      * available.  Only one writer can acquire the write lock, and
169      * when held, no readers can acquire the read lock.</p>
170      *
171      * <p>If there are no readers and no waiting writers, mark as
172      * having an active writer and return.  Otherwise, add a lock to the
173      * end of the waiting writer list, and block on it.  Caller
174      * must call releaseWrite when done (for example, in a finally
175      * block).<p>
176      */
acquireWrite()177     public void acquireWrite() {
178         if (stats != null) {    // stats is null by default
179             synchronized (this) {
180                 stats._wc++;
181                 if (rwl.getReadLockCount() > 0 || rwl.isWriteLocked()) {
182                     stats._wwc++;
183                 }
184             }
185         }
186         rwl.writeLock().lock();
187     }
188 
189     /**
190      * <p>Release the write lock and return.  An error will be thrown
191      * if the write lock is not currently held.</p>
192      *
193      * <p>If there are waiting readers, make them all active and
194      * notify all of them.  Otherwise, notify the oldest waiting
195      * writer, if any.  Call when finished with work controlled by
196      * acquireWrite.</p>
197      */
releaseWrite()198     public void releaseWrite() {
199         rwl.writeLock().unlock();
200     }
201 }
202