All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.icu.impl.ICURWLock Maven / Gradle / Ivy

Go to download

International Component for Unicode for Java (ICU4J) is a mature, widely used Java library providing Unicode and Globalization support

There is a newer version: 76.1
Show newest version
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/**
 *******************************************************************************
 * Copyright (C) 2001-2013, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.util.concurrent.locks.ReentrantReadWriteLock;


/**
 * 

A Reader/Writer lock originally written for ICU service * implementation. The internal implementation was replaced * with the JDK's stock read write lock (ReentrantReadWriteLock) * for ICU 52.

* *

This assumes that there will be little writing contention. * It also doesn't allow active readers to acquire and release * a write lock, or deal with priority inversion issues.

* *

Access to the lock should be enclosed in a try/finally block * in order to ensure that the lock is always released in case of * exceptions:

 * try {
 *     lock.acquireRead();
 *     // use service protected by the lock
 * }
 * finally {
 *     lock.releaseRead();
 * }
 * 

* *

The lock provides utility methods getStats and clearStats * to return statistics on the use of the lock.

*/ public class ICURWLock { private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private Stats stats = null; /** * Internal class used to gather statistics on the RWLock. */ public final static class Stats { /** * Number of times read access granted (read count). */ public int _rc; /** * Number of times concurrent read access granted (multiple read count). */ public int _mrc; /** * Number of times blocked for read (waiting reader count). */ public int _wrc; // wait for read /** * Number of times write access granted (writer count). */ public int _wc; /** * Number of times blocked for write (waiting writer count). */ public int _wwc; private Stats() { } private Stats(int rc, int mrc, int wrc, int wc, int wwc) { this._rc = rc; this._mrc = mrc; this._wrc = wrc; this._wc = wc; this._wwc = wwc; } private Stats(Stats rhs) { this(rhs._rc, rhs._mrc, rhs._wrc, rhs._wc, rhs._wwc); } /** * Return a string listing all the stats. */ @Override public String toString() { return " rc: " + _rc + " mrc: " + _mrc + " wrc: " + _wrc + " wc: " + _wc + " wwc: " + _wwc; } } /** * Reset the stats. Returns existing stats, if any. */ public synchronized Stats resetStats() { Stats result = stats; stats = new Stats(); return result; } /** * Clear the stats (stop collecting stats). Returns existing stats, if any. */ public synchronized Stats clearStats() { Stats result = stats; stats = null; return result; } /** * Return a snapshot of the current stats. This does not reset the stats. */ public synchronized Stats getStats() { return stats == null ? null : new Stats(stats); } /** *

Acquire a read lock, blocking until a read lock is * available. Multiple readers can concurrently hold the read * lock.

* *

If there's a writer, or a waiting writer, increment the * waiting reader count and block on this. Otherwise * increment the active reader count and return. Caller must call * releaseRead when done (for example, in a finally block).

*/ public void acquireRead() { if (stats != null) { // stats is null by default synchronized (this) { stats._rc++; if (rwl.getReadLockCount() > 0) { stats._mrc++; } if (rwl.isWriteLocked()) { stats._wrc++; } } } rwl.readLock().lock(); } /** *

Release a read lock and return. An error will be thrown * if a read lock is not currently held.

* *

If this is the last active reader, notify the oldest * waiting writer. Call when finished with work * controlled by acquireRead.

*/ public void releaseRead() { rwl.readLock().unlock(); } /** *

Acquire the write lock, blocking until the write lock is * available. Only one writer can acquire the write lock, and * when held, no readers can acquire the read lock.

* *

If there are no readers and no waiting writers, mark as * having an active writer and return. Otherwise, add a lock to the * end of the waiting writer list, and block on it. Caller * must call releaseWrite when done (for example, in a finally * block).

*/ public void acquireWrite() { if (stats != null) { // stats is null by default synchronized (this) { stats._wc++; if (rwl.getReadLockCount() > 0 || rwl.isWriteLocked()) { stats._wwc++; } } } rwl.writeLock().lock(); } /** *

Release the write lock and return. An error will be thrown * if the write lock is not currently held.

* *

If there are waiting readers, make them all active and * notify all of them. Otherwise, notify the oldest waiting * writer, if any. Call when finished with work controlled by * acquireWrite.

*/ public void releaseWrite() { rwl.writeLock().unlock(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy