aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/icu/common/unifiedcache.cpp
diff options
context:
space:
mode:
authorneksard <neksard@yandex-team.ru>2022-02-10 16:45:33 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:45:33 +0300
commit1d9c550e7c38e051d7961f576013a482003a70d9 (patch)
treeb2cc84ee7850122e7ccf51d0ea21e4fa7e7a5685 /contrib/libs/icu/common/unifiedcache.cpp
parent8f7cf138264e0caa318144bf8a2c950e0b0a8593 (diff)
downloadydb-1d9c550e7c38e051d7961f576013a482003a70d9.tar.gz
Restoring authorship annotation for <neksard@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/icu/common/unifiedcache.cpp')
-rw-r--r--contrib/libs/icu/common/unifiedcache.cpp716
1 files changed, 358 insertions, 358 deletions
diff --git a/contrib/libs/icu/common/unifiedcache.cpp b/contrib/libs/icu/common/unifiedcache.cpp
index b05a63977e..f2dd916559 100644
--- a/contrib/libs/icu/common/unifiedcache.cpp
+++ b/contrib/libs/icu/common/unifiedcache.cpp
@@ -1,111 +1,111 @@
// © 2016 and later: Unicode, Inc. and others.
-// License & terms of use: http://www.unicode.org/copyright.html
-/*
-******************************************************************************
+// License & terms of use: http://www.unicode.org/copyright.html
+/*
+******************************************************************************
* Copyright (C) 2015, International Business Machines Corporation and
* others. All Rights Reserved.
-******************************************************************************
+******************************************************************************
*
* File unifiedcache.cpp
-******************************************************************************
-*/
-
-#include "unifiedcache.h"
+******************************************************************************
+*/
+
+#include "unifiedcache.h"
#include <algorithm> // For std::max()
#include <mutex>
-#include "uassert.h"
+#include "uassert.h"
#include "uhash.h"
-#include "ucln_cmn.h"
-
-static icu::UnifiedCache *gCache = NULL;
+#include "ucln_cmn.h"
+
+static icu::UnifiedCache *gCache = NULL;
static std::mutex *gCacheMutex = nullptr;
static std::condition_variable *gInProgressValueAddedCond;
-static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
+static icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER;
-static const int32_t MAX_EVICT_ITERATIONS = 10;
+static const int32_t MAX_EVICT_ITERATIONS = 10;
static const int32_t DEFAULT_MAX_UNUSED = 1000;
static const int32_t DEFAULT_PERCENTAGE_OF_IN_USE = 100;
-
-
-U_CDECL_BEGIN
-static UBool U_CALLCONV unifiedcache_cleanup() {
- gCacheInitOnce.reset();
+
+
+U_CDECL_BEGIN
+static UBool U_CALLCONV unifiedcache_cleanup() {
+ gCacheInitOnce.reset();
delete gCache;
gCache = nullptr;
gCacheMutex->~mutex();
gCacheMutex = nullptr;
gInProgressValueAddedCond->~condition_variable();
gInProgressValueAddedCond = nullptr;
- return TRUE;
-}
-U_CDECL_END
-
-
-U_NAMESPACE_BEGIN
-
-U_CAPI int32_t U_EXPORT2
-ucache_hashKeys(const UHashTok key) {
- const CacheKeyBase *ckey = (const CacheKeyBase *) key.pointer;
- return ckey->hashCode();
-}
-
-U_CAPI UBool U_EXPORT2
-ucache_compareKeys(const UHashTok key1, const UHashTok key2) {
- const CacheKeyBase *p1 = (const CacheKeyBase *) key1.pointer;
- const CacheKeyBase *p2 = (const CacheKeyBase *) key2.pointer;
- return *p1 == *p2;
-}
-
-U_CAPI void U_EXPORT2
-ucache_deleteKey(void *obj) {
- CacheKeyBase *p = (CacheKeyBase *) obj;
- delete p;
-}
-
-CacheKeyBase::~CacheKeyBase() {
-}
-
-static void U_CALLCONV cacheInit(UErrorCode &status) {
- U_ASSERT(gCache == NULL);
- ucln_common_registerCleanup(
- UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup);
-
+ return TRUE;
+}
+U_CDECL_END
+
+
+U_NAMESPACE_BEGIN
+
+U_CAPI int32_t U_EXPORT2
+ucache_hashKeys(const UHashTok key) {
+ const CacheKeyBase *ckey = (const CacheKeyBase *) key.pointer;
+ return ckey->hashCode();
+}
+
+U_CAPI UBool U_EXPORT2
+ucache_compareKeys(const UHashTok key1, const UHashTok key2) {
+ const CacheKeyBase *p1 = (const CacheKeyBase *) key1.pointer;
+ const CacheKeyBase *p2 = (const CacheKeyBase *) key2.pointer;
+ return *p1 == *p2;
+}
+
+U_CAPI void U_EXPORT2
+ucache_deleteKey(void *obj) {
+ CacheKeyBase *p = (CacheKeyBase *) obj;
+ delete p;
+}
+
+CacheKeyBase::~CacheKeyBase() {
+}
+
+static void U_CALLCONV cacheInit(UErrorCode &status) {
+ U_ASSERT(gCache == NULL);
+ ucln_common_registerCleanup(
+ UCLN_COMMON_UNIFIED_CACHE, unifiedcache_cleanup);
+
gCacheMutex = STATIC_NEW(std::mutex);
gInProgressValueAddedCond = STATIC_NEW(std::condition_variable);
- gCache = new UnifiedCache(status);
- if (gCache == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- }
- if (U_FAILURE(status)) {
- delete gCache;
- gCache = NULL;
- return;
- }
-}
-
-UnifiedCache *UnifiedCache::getInstance(UErrorCode &status) {
- umtx_initOnce(gCacheInitOnce, &cacheInit, status);
- if (U_FAILURE(status)) {
- return NULL;
- }
- U_ASSERT(gCache != NULL);
- return gCache;
-}
-
-UnifiedCache::UnifiedCache(UErrorCode &status) :
- fHashtable(NULL),
- fEvictPos(UHASH_FIRST),
+ gCache = new UnifiedCache(status);
+ if (gCache == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ }
+ if (U_FAILURE(status)) {
+ delete gCache;
+ gCache = NULL;
+ return;
+ }
+}
+
+UnifiedCache *UnifiedCache::getInstance(UErrorCode &status) {
+ umtx_initOnce(gCacheInitOnce, &cacheInit, status);
+ if (U_FAILURE(status)) {
+ return NULL;
+ }
+ U_ASSERT(gCache != NULL);
+ return gCache;
+}
+
+UnifiedCache::UnifiedCache(UErrorCode &status) :
+ fHashtable(NULL),
+ fEvictPos(UHASH_FIRST),
fNumValuesTotal(0),
fNumValuesInUse(0),
- fMaxUnused(DEFAULT_MAX_UNUSED),
- fMaxPercentageOfInUse(DEFAULT_PERCENTAGE_OF_IN_USE),
+ fMaxUnused(DEFAULT_MAX_UNUSED),
+ fMaxPercentageOfInUse(DEFAULT_PERCENTAGE_OF_IN_USE),
fAutoEvictedCount(0),
fNoValue(nullptr) {
- if (U_FAILURE(status)) {
- return;
- }
+ if (U_FAILURE(status)) {
+ return;
+ }
fNoValue = new SharedObject();
if (fNoValue == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR;
@@ -115,155 +115,155 @@ UnifiedCache::UnifiedCache(UErrorCode &status) :
fNoValue->hardRefCount = 1; // when other references to it are removed.
fNoValue->cachePtr = this;
- fHashtable = uhash_open(
- &ucache_hashKeys,
- &ucache_compareKeys,
- NULL,
- &status);
- if (U_FAILURE(status)) {
- return;
- }
- uhash_setKeyDeleter(fHashtable, &ucache_deleteKey);
-}
-
-void UnifiedCache::setEvictionPolicy(
- int32_t count, int32_t percentageOfInUseItems, UErrorCode &status) {
- if (U_FAILURE(status)) {
- return;
- }
- if (count < 0 || percentageOfInUseItems < 0) {
- status = U_ILLEGAL_ARGUMENT_ERROR;
- return;
- }
+ fHashtable = uhash_open(
+ &ucache_hashKeys,
+ &ucache_compareKeys,
+ NULL,
+ &status);
+ if (U_FAILURE(status)) {
+ return;
+ }
+ uhash_setKeyDeleter(fHashtable, &ucache_deleteKey);
+}
+
+void UnifiedCache::setEvictionPolicy(
+ int32_t count, int32_t percentageOfInUseItems, UErrorCode &status) {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ if (count < 0 || percentageOfInUseItems < 0) {
+ status = U_ILLEGAL_ARGUMENT_ERROR;
+ return;
+ }
std::lock_guard<std::mutex> lock(*gCacheMutex);
- fMaxUnused = count;
- fMaxPercentageOfInUse = percentageOfInUseItems;
-}
-
-int32_t UnifiedCache::unusedCount() const {
+ fMaxUnused = count;
+ fMaxPercentageOfInUse = percentageOfInUseItems;
+}
+
+int32_t UnifiedCache::unusedCount() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
return uhash_count(fHashtable) - fNumValuesInUse;
-}
-
-int64_t UnifiedCache::autoEvictedCount() const {
+}
+
+int64_t UnifiedCache::autoEvictedCount() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
- return fAutoEvictedCount;
-}
-
-int32_t UnifiedCache::keyCount() const {
+ return fAutoEvictedCount;
+}
+
+int32_t UnifiedCache::keyCount() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
- return uhash_count(fHashtable);
-}
-
-void UnifiedCache::flush() const {
+ return uhash_count(fHashtable);
+}
+
+void UnifiedCache::flush() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
-
- // Use a loop in case cache items that are flushed held hard references to
- // other cache items making those additional cache items eligible for
- // flushing.
- while (_flush(FALSE));
-}
-
+
+ // Use a loop in case cache items that are flushed held hard references to
+ // other cache items making those additional cache items eligible for
+ // flushing.
+ while (_flush(FALSE));
+}
+
void UnifiedCache::handleUnreferencedObject() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
--fNumValuesInUse;
_runEvictionSlice();
}
-#ifdef UNIFIED_CACHE_DEBUG
-#include <stdio.h>
-
-void UnifiedCache::dump() {
- UErrorCode status = U_ZERO_ERROR;
- const UnifiedCache *cache = getInstance(status);
- if (U_FAILURE(status)) {
- fprintf(stderr, "Unified Cache: Error fetching cache.\n");
- return;
- }
- cache->dumpContents();
-}
-
-void UnifiedCache::dumpContents() const {
+#ifdef UNIFIED_CACHE_DEBUG
+#include <stdio.h>
+
+void UnifiedCache::dump() {
+ UErrorCode status = U_ZERO_ERROR;
+ const UnifiedCache *cache = getInstance(status);
+ if (U_FAILURE(status)) {
+ fprintf(stderr, "Unified Cache: Error fetching cache.\n");
+ return;
+ }
+ cache->dumpContents();
+}
+
+void UnifiedCache::dumpContents() const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
- _dumpContents();
-}
-
-// Dumps content of cache.
-// On entry, gCacheMutex must be held.
-// On exit, cache contents dumped to stderr.
-void UnifiedCache::_dumpContents() const {
- int32_t pos = UHASH_FIRST;
- const UHashElement *element = uhash_nextElement(fHashtable, &pos);
- char buffer[256];
- int32_t cnt = 0;
- for (; element != NULL; element = uhash_nextElement(fHashtable, &pos)) {
- const SharedObject *sharedObject =
- (const SharedObject *) element->value.pointer;
- const CacheKeyBase *key =
- (const CacheKeyBase *) element->key.pointer;
- if (sharedObject->hasHardReferences()) {
- ++cnt;
- fprintf(
- stderr,
+ _dumpContents();
+}
+
+// Dumps content of cache.
+// On entry, gCacheMutex must be held.
+// On exit, cache contents dumped to stderr.
+void UnifiedCache::_dumpContents() const {
+ int32_t pos = UHASH_FIRST;
+ const UHashElement *element = uhash_nextElement(fHashtable, &pos);
+ char buffer[256];
+ int32_t cnt = 0;
+ for (; element != NULL; element = uhash_nextElement(fHashtable, &pos)) {
+ const SharedObject *sharedObject =
+ (const SharedObject *) element->value.pointer;
+ const CacheKeyBase *key =
+ (const CacheKeyBase *) element->key.pointer;
+ if (sharedObject->hasHardReferences()) {
+ ++cnt;
+ fprintf(
+ stderr,
"Unified Cache: Key '%s', error %d, value %p, total refcount %d, soft refcount %d\n",
- key->writeDescription(buffer, 256),
- key->creationStatus,
+ key->writeDescription(buffer, 256),
+ key->creationStatus,
sharedObject == fNoValue ? NULL :sharedObject,
- sharedObject->getRefCount(),
- sharedObject->getSoftRefCount());
- }
- }
- fprintf(stderr, "Unified Cache: %d out of a total of %d still have hard references\n", cnt, uhash_count(fHashtable));
-}
-#endif
-
-UnifiedCache::~UnifiedCache() {
- // Try our best to clean up first.
- flush();
- {
- // Now all that should be left in the cache are entries that refer to
+ sharedObject->getRefCount(),
+ sharedObject->getSoftRefCount());
+ }
+ }
+ fprintf(stderr, "Unified Cache: %d out of a total of %d still have hard references\n", cnt, uhash_count(fHashtable));
+}
+#endif
+
+UnifiedCache::~UnifiedCache() {
+ // Try our best to clean up first.
+ flush();
+ {
+ // Now all that should be left in the cache are entries that refer to
// each other and entries with hard references from outside the cache.
- // Nothing we can do about these so proceed to wipe out the cache.
+ // Nothing we can do about these so proceed to wipe out the cache.
std::lock_guard<std::mutex> lock(*gCacheMutex);
- _flush(TRUE);
- }
- uhash_close(fHashtable);
+ _flush(TRUE);
+ }
+ uhash_close(fHashtable);
fHashtable = nullptr;
delete fNoValue;
fNoValue = nullptr;
-}
-
-const UHashElement *
-UnifiedCache::_nextElement() const {
- const UHashElement *element = uhash_nextElement(fHashtable, &fEvictPos);
- if (element == NULL) {
- fEvictPos = UHASH_FIRST;
- return uhash_nextElement(fHashtable, &fEvictPos);
- }
- return element;
-}
-
-UBool UnifiedCache::_flush(UBool all) const {
- UBool result = FALSE;
- int32_t origSize = uhash_count(fHashtable);
- for (int32_t i = 0; i < origSize; ++i) {
- const UHashElement *element = _nextElement();
+}
+
+const UHashElement *
+UnifiedCache::_nextElement() const {
+ const UHashElement *element = uhash_nextElement(fHashtable, &fEvictPos);
+ if (element == NULL) {
+ fEvictPos = UHASH_FIRST;
+ return uhash_nextElement(fHashtable, &fEvictPos);
+ }
+ return element;
+}
+
+UBool UnifiedCache::_flush(UBool all) const {
+ UBool result = FALSE;
+ int32_t origSize = uhash_count(fHashtable);
+ for (int32_t i = 0; i < origSize; ++i) {
+ const UHashElement *element = _nextElement();
if (element == nullptr) {
break;
}
- if (all || _isEvictable(element)) {
- const SharedObject *sharedObject =
- (const SharedObject *) element->value.pointer;
+ if (all || _isEvictable(element)) {
+ const SharedObject *sharedObject =
+ (const SharedObject *) element->value.pointer;
U_ASSERT(sharedObject->cachePtr == this);
- uhash_removeElement(fHashtable, element);
+ uhash_removeElement(fHashtable, element);
removeSoftRef(sharedObject); // Deletes the sharedObject when softRefCount goes to zero.
- result = TRUE;
- }
- }
- return result;
-}
-
-int32_t UnifiedCache::_computeCountOfItemsToEvict() const {
+ result = TRUE;
+ }
+ }
+ return result;
+}
+
+int32_t UnifiedCache::_computeCountOfItemsToEvict() const {
int32_t totalItems = uhash_count(fHashtable);
int32_t evictableItems = totalItems - fNumValuesInUse;
@@ -271,87 +271,87 @@ int32_t UnifiedCache::_computeCountOfItemsToEvict() const {
int32_t unusedLimit = std::max(unusedLimitByPercentage, fMaxUnused);
int32_t countOfItemsToEvict = std::max(0, evictableItems - unusedLimit);
return countOfItemsToEvict;
-}
-
-void UnifiedCache::_runEvictionSlice() const {
- int32_t maxItemsToEvict = _computeCountOfItemsToEvict();
- if (maxItemsToEvict <= 0) {
- return;
- }
- for (int32_t i = 0; i < MAX_EVICT_ITERATIONS; ++i) {
- const UHashElement *element = _nextElement();
+}
+
+void UnifiedCache::_runEvictionSlice() const {
+ int32_t maxItemsToEvict = _computeCountOfItemsToEvict();
+ if (maxItemsToEvict <= 0) {
+ return;
+ }
+ for (int32_t i = 0; i < MAX_EVICT_ITERATIONS; ++i) {
+ const UHashElement *element = _nextElement();
if (element == nullptr) {
break;
}
- if (_isEvictable(element)) {
- const SharedObject *sharedObject =
- (const SharedObject *) element->value.pointer;
- uhash_removeElement(fHashtable, element);
+ if (_isEvictable(element)) {
+ const SharedObject *sharedObject =
+ (const SharedObject *) element->value.pointer;
+ uhash_removeElement(fHashtable, element);
removeSoftRef(sharedObject); // Deletes sharedObject when SoftRefCount goes to zero.
- ++fAutoEvictedCount;
- if (--maxItemsToEvict == 0) {
- break;
- }
- }
- }
-}
-
-void UnifiedCache::_putNew(
+ ++fAutoEvictedCount;
+ if (--maxItemsToEvict == 0) {
+ break;
+ }
+ }
+ }
+}
+
+void UnifiedCache::_putNew(
const CacheKeyBase &key,
- const SharedObject *value,
- const UErrorCode creationStatus,
- UErrorCode &status) const {
- if (U_FAILURE(status)) {
- return;
- }
- CacheKeyBase *keyToAdopt = key.clone();
- if (keyToAdopt == NULL) {
- status = U_MEMORY_ALLOCATION_ERROR;
- return;
- }
- keyToAdopt->fCreationStatus = creationStatus;
+ const SharedObject *value,
+ const UErrorCode creationStatus,
+ UErrorCode &status) const {
+ if (U_FAILURE(status)) {
+ return;
+ }
+ CacheKeyBase *keyToAdopt = key.clone();
+ if (keyToAdopt == NULL) {
+ status = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+ keyToAdopt->fCreationStatus = creationStatus;
if (value->softRefCount == 0) {
- _registerMaster(keyToAdopt, value);
- }
+ _registerMaster(keyToAdopt, value);
+ }
void *oldValue = uhash_put(fHashtable, keyToAdopt, (void *) value, &status);
U_ASSERT(oldValue == nullptr);
(void)oldValue;
- if (U_SUCCESS(status)) {
+ if (U_SUCCESS(status)) {
value->softRefCount++;
- }
-}
-
-void UnifiedCache::_putIfAbsentAndGet(
- const CacheKeyBase &key,
- const SharedObject *&value,
- UErrorCode &status) const {
+ }
+}
+
+void UnifiedCache::_putIfAbsentAndGet(
+ const CacheKeyBase &key,
+ const SharedObject *&value,
+ UErrorCode &status) const {
std::lock_guard<std::mutex> lock(*gCacheMutex);
- const UHashElement *element = uhash_find(fHashtable, &key);
- if (element != NULL && !_inProgress(element)) {
- _fetch(element, value, status);
- return;
- }
- if (element == NULL) {
- UErrorCode putError = U_ZERO_ERROR;
- // best-effort basis only.
- _putNew(key, value, status, putError);
- } else {
- _put(element, value, status);
- }
- // Run an eviction slice. This will run even if we added a master entry
- // which doesn't increase the unused count, but that is still o.k
- _runEvictionSlice();
-}
-
-
-UBool UnifiedCache::_poll(
- const CacheKeyBase &key,
- const SharedObject *&value,
- UErrorCode &status) const {
- U_ASSERT(value == NULL);
- U_ASSERT(status == U_ZERO_ERROR);
+ const UHashElement *element = uhash_find(fHashtable, &key);
+ if (element != NULL && !_inProgress(element)) {
+ _fetch(element, value, status);
+ return;
+ }
+ if (element == NULL) {
+ UErrorCode putError = U_ZERO_ERROR;
+ // best-effort basis only.
+ _putNew(key, value, status, putError);
+ } else {
+ _put(element, value, status);
+ }
+ // Run an eviction slice. This will run even if we added a master entry
+ // which doesn't increase the unused count, but that is still o.k
+ _runEvictionSlice();
+}
+
+
+UBool UnifiedCache::_poll(
+ const CacheKeyBase &key,
+ const SharedObject *&value,
+ UErrorCode &status) const {
+ U_ASSERT(value == NULL);
+ U_ASSERT(status == U_ZERO_ERROR);
std::unique_lock<std::mutex> lock(*gCacheMutex);
- const UHashElement *element = uhash_find(fHashtable, &key);
+ const UHashElement *element = uhash_find(fHashtable, &key);
// If the hash table contains an inProgress placeholder entry for this key,
// this means that another thread is currently constructing the value object.
@@ -359,126 +359,126 @@ UBool UnifiedCache::_poll(
while (element != NULL && _inProgress(element)) {
gInProgressValueAddedCond->wait(lock);
element = uhash_find(fHashtable, &key);
- }
+ }
// If the hash table contains an entry for the key,
// fetch out the contents and return them.
- if (element != NULL) {
+ if (element != NULL) {
_fetch(element, value, status);
- return TRUE;
- }
+ return TRUE;
+ }
// The hash table contained nothing for this key.
// Insert an inProgress place holder value.
// Our caller will create the final value and update the hash table.
_putNew(key, fNoValue, U_ZERO_ERROR, status);
- return FALSE;
-}
-
-void UnifiedCache::_get(
- const CacheKeyBase &key,
- const SharedObject *&value,
- const void *creationContext,
- UErrorCode &status) const {
- U_ASSERT(value == NULL);
- U_ASSERT(status == U_ZERO_ERROR);
- if (_poll(key, value, status)) {
+ return FALSE;
+}
+
+void UnifiedCache::_get(
+ const CacheKeyBase &key,
+ const SharedObject *&value,
+ const void *creationContext,
+ UErrorCode &status) const {
+ U_ASSERT(value == NULL);
+ U_ASSERT(status == U_ZERO_ERROR);
+ if (_poll(key, value, status)) {
if (value == fNoValue) {
- SharedObject::clearPtr(value);
- }
- return;
- }
- if (U_FAILURE(status)) {
- return;
- }
- value = key.createObject(creationContext, status);
- U_ASSERT(value == NULL || value->hasHardReferences());
- U_ASSERT(value != NULL || status != U_ZERO_ERROR);
- if (value == NULL) {
+ SharedObject::clearPtr(value);
+ }
+ return;
+ }
+ if (U_FAILURE(status)) {
+ return;
+ }
+ value = key.createObject(creationContext, status);
+ U_ASSERT(value == NULL || value->hasHardReferences());
+ U_ASSERT(value != NULL || status != U_ZERO_ERROR);
+ if (value == NULL) {
SharedObject::copyPtr(fNoValue, value);
- }
- _putIfAbsentAndGet(key, value, status);
+ }
+ _putIfAbsentAndGet(key, value, status);
if (value == fNoValue) {
- SharedObject::clearPtr(value);
- }
-}
-
-void UnifiedCache::_registerMaster(
+ SharedObject::clearPtr(value);
+ }
+}
+
+void UnifiedCache::_registerMaster(
const CacheKeyBase *theKey, const SharedObject *value) const {
theKey->fIsMaster = true;
value->cachePtr = this;
++fNumValuesTotal;
++fNumValuesInUse;
-}
-
-void UnifiedCache::_put(
+}
+
+void UnifiedCache::_put(
const UHashElement *element,
- const SharedObject *value,
- const UErrorCode status) const {
- U_ASSERT(_inProgress(element));
- const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
- const SharedObject *oldValue = (const SharedObject *) element->value.pointer;
- theKey->fCreationStatus = status;
+ const SharedObject *value,
+ const UErrorCode status) const {
+ U_ASSERT(_inProgress(element));
+ const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
+ const SharedObject *oldValue = (const SharedObject *) element->value.pointer;
+ theKey->fCreationStatus = status;
if (value->softRefCount == 0) {
- _registerMaster(theKey, value);
- }
+ _registerMaster(theKey, value);
+ }
value->softRefCount++;
- UHashElement *ptr = const_cast<UHashElement *>(element);
- ptr->value.pointer = (void *) value;
+ UHashElement *ptr = const_cast<UHashElement *>(element);
+ ptr->value.pointer = (void *) value;
U_ASSERT(oldValue == fNoValue);
removeSoftRef(oldValue);
-
- // Tell waiting threads that we replace in-progress status with
- // an error.
+
+ // Tell waiting threads that we replace in-progress status with
+ // an error.
gInProgressValueAddedCond->notify_all();
-}
-
-void UnifiedCache::_fetch(
- const UHashElement *element,
- const SharedObject *&value,
+}
+
+void UnifiedCache::_fetch(
+ const UHashElement *element,
+ const SharedObject *&value,
UErrorCode &status) const {
- const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
- status = theKey->fCreationStatus;
-
+ const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
+ status = theKey->fCreationStatus;
+
// Since we have the cache lock, calling regular SharedObject add/removeRef
- // could cause us to deadlock on ourselves since they may need to lock
- // the cache mutex.
+ // could cause us to deadlock on ourselves since they may need to lock
+ // the cache mutex.
removeHardRef(value);
value = static_cast<const SharedObject *>(element->value.pointer);
addHardRef(value);
-}
-
+}
+
UBool UnifiedCache::_inProgress(const UHashElement* element) const {
- UErrorCode status = U_ZERO_ERROR;
+ UErrorCode status = U_ZERO_ERROR;
const SharedObject * value = NULL;
- _fetch(element, value, status);
- UBool result = _inProgress(value, status);
+ _fetch(element, value, status);
+ UBool result = _inProgress(value, status);
removeHardRef(value);
- return result;
-}
-
-UBool UnifiedCache::_inProgress(
+ return result;
+}
+
+UBool UnifiedCache::_inProgress(
const SharedObject* theValue, UErrorCode creationStatus) const {
return (theValue == fNoValue && creationStatus == U_ZERO_ERROR);
-}
-
+}
+
UBool UnifiedCache::_isEvictable(const UHashElement *element) const
{
- const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
- const SharedObject *theValue =
- (const SharedObject *) element->value.pointer;
-
- // Entries that are under construction are never evictable
- if (_inProgress(theValue, theKey->fCreationStatus)) {
- return FALSE;
- }
-
- // We can evict entries that are either not a master or have just
- // one reference (The one reference being from the cache itself).
+ const CacheKeyBase *theKey = (const CacheKeyBase *) element->key.pointer;
+ const SharedObject *theValue =
+ (const SharedObject *) element->value.pointer;
+
+ // Entries that are under construction are never evictable
+ if (_inProgress(theValue, theKey->fCreationStatus)) {
+ return FALSE;
+ }
+
+ // We can evict entries that are either not a master or have just
+ // one reference (The one reference being from the cache itself).
return (!theKey->fIsMaster || (theValue->softRefCount == 1 && theValue->noHardReferences()));
-}
-
+}
+
void UnifiedCache::removeSoftRef(const SharedObject *value) const {
U_ASSERT(value->cachePtr == this);
U_ASSERT(value->softRefCount > 0);
@@ -519,4 +519,4 @@ int32_t UnifiedCache::addHardRef(const SharedObject *value) const {
return refCount;
}
-U_NAMESPACE_END
+U_NAMESPACE_END