From 10f1e3259e16e6bf25a25b6a0ae5076945c068ca Mon Sep 17 00:00:00 2001
From: Yoshito Umaoka A simple Reader/Writer lock. 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. 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
@@ -31,13 +35,9 @@ package com.ibm.icu.impl;
* to return statistics on the use of the lock. Acquire a read lock, blocking until a read lock is
* available. Multiple readers can concurrently hold the read
@@ -209,20 +131,18 @@ public class ICURWLock {
* releaseRead when done (for example, in a finally block).
*/ public void acquireWrite() { - if (!getWrite()) { - for (;;) { - try { - synchronized (writeLock) { - writeLock.wait(); - } - if (retryWrite()) { - return; - } - } - catch (InterruptedException e) { + if (stats != null) { // stats is null by default + synchronized (this) { + stats._wc++; + if (rwl.getReadLockCount() > 0 || rwl.isWriteLocked()) { + stats._wwc++; } } } + rwl.writeLock().lock(); } /** @@ -279,19 +190,6 @@ public class ICURWLock { * acquireWrite.
*/ public void releaseWrite() { - switch (finishWrite()) { - case NOTIFY_WRITERS: - synchronized (writeLock) { - writeLock.notify(); - } - break; - case NOTIFY_READERS: - synchronized (readLock) { - readLock.notifyAll(); - } - break; - case NOTIFY_NONE: - break; - } + rwl.writeLock().unlock(); } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUService.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUService.java index 486a06bfe31..99fc9280bee 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUService.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUService.java @@ -1,6 +1,6 @@ /** ******************************************************************************* - * Copyright (C) 2001-2011, International Business Machines Corporation and * + * Copyright (C) 2001-2013, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -959,8 +959,10 @@ public class ICUService extends ICUNotifier { } /** - * Return a string describing the statistics for this service. - * This also resets the statistics. Used for debugging purposes. + * When the statistics for this service is already enabled, + * return the log and resets he statistics. + * When the statistics is not enabled, this method enable + * the statistics. Used for debugging purposes. */ public String stats() { ICURWLock.Stats stats = factoryLock.resetStats(); diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceTest.java index f50e50c5f97..e6295d535d2 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceTest.java @@ -1,6 +1,6 @@ /** ******************************************************************************* - * Copyright (C) 2001-2010, International Business Machines Corporation and * + * Copyright (C) 2001-2013, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -879,6 +879,8 @@ public class ICUServiceTest extends TestFmwk // ICURWLock ICURWLock rwlock = new ICURWLock(); + rwlock.resetStats(); + rwlock.acquireRead(); rwlock.releaseRead(); @@ -896,7 +898,7 @@ public class ICUServiceTest extends TestFmwk rwlock.releaseRead(); errln("no error thrown"); } - catch (IllegalStateException e) { + catch (Exception e) { logln("OK: " + e.getMessage()); } @@ -904,7 +906,7 @@ public class ICUServiceTest extends TestFmwk rwlock.releaseWrite(); errln("no error thrown"); } - catch (IllegalStateException e) { + catch (Exception e) { logln("OK: " + e.getMessage()); } diff --git a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java index 161e08d370c..e984dca7ae0 100644 --- a/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java +++ b/icu4j/main/tests/core/src/com/ibm/icu/dev/test/util/ICUServiceThreadTest.java @@ -1,6 +1,6 @@ /** ******************************************************************************* - * Copyright (C) 2001-2010, International Business Machines Corporation and * + * Copyright (C) 2001-2013, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -371,6 +371,7 @@ public class ICUServiceThreadTest extends TestFmwk stableService = new ICULocaleService(); registerFactories(stableService, getFactoryCollection(50)); } + if (PRINTSTATS) stableService.stats(); // Enable the stats collection return stableService; } private ICUService stableService; @@ -413,6 +414,7 @@ public class ICUServiceThreadTest extends TestFmwk // run register/unregister on a service public void Test03_ConcurrentRegUnreg() { ICUService service = new ICULocaleService(); + if (PRINTSTATS) service.stats(); // Enable the stats collection for (int i = 0; i < 5; ++i) { new RegisterFactoryThread("[" + i + "]", service, 0, this).start(); } @@ -425,6 +427,7 @@ public class ICUServiceThreadTest extends TestFmwk public void Test04_WitheringService() { ICUService service = new ICULocaleService(); + if (PRINTSTATS) service.stats(); // Enable the stats collection Collection fc = getFactoryCollection(50); registerFactories(service, fc); @@ -452,6 +455,7 @@ public class ICUServiceThreadTest extends TestFmwk // run for ten seconds public void Test05_ConcurrentEverything() { ICUService service = new ICULocaleService(); + if (PRINTSTATS) service.stats(); // Enable the stats collection new RegisterFactoryThread("", service, 500, this).start();