164339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// Copyright (C) 2016 and later: Unicode, Inc. and others. 264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 58de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert* Copyright (C) 2015-2016, International Business Machines 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* sharedobject.h 9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef __SHAREDOBJECT_H__ 12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define __SHAREDOBJECT_H__ 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/uobject.h" 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "umutex.h" 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/** 21c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Base class for unified cache exposing enough methods to SharedObject 22c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * instances to allow their addRef() and removeRef() methods to 23c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * update cache metrics. No other part of ICU, except for SharedObject, 24c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * should directly call the methods of this base class. 25c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 268de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubertclass U_COMMON_API UnifiedCacheBase : public UObject { 27c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertpublic: 28c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnifiedCacheBase() { } 29c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 30c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 31c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Called by addRefWhileHoldingCacheLock() when the hard reference count 32c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * of its instance goes from 0 to 1. 33c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 34c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert virtual void incrementItemsInUse() const = 0; 35c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 36c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 37c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Called by removeRef() when the hard reference count of its instance 38c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * drops from 1 to 0. 39c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 40c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert virtual void decrementItemsInUseWithLockingAndEviction() const = 0; 41c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 42c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 43c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Called by removeRefWhileHoldingCacheLock() when the hard reference 44c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * count of its instance drops from 1 to 0. 45c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 46c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert virtual void decrementItemsInUse() const = 0; 47c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert virtual ~UnifiedCacheBase(); 48c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertprivate: 49c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnifiedCacheBase(const UnifiedCacheBase &); 50c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UnifiedCacheBase &operator=(const UnifiedCacheBase &); 51c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}; 52c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 53c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert/** 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Base class for shared, reference-counted, auto-deleted objects. 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Subclasses can be immutable. 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If they are mutable, then they must implement their copy constructor 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * so that copyOnWrite() works. 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Either stack-allocate, use LocalPointer, or use addRef()/removeRef(). 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Sharing requires reference-counting. 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass U_COMMON_API SharedObject : public UObject { 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic: 64f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** Initializes totalRefCount, softRefCount to 0. */ 65c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert SharedObject() : 66c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert totalRefCount(0), 67c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert softRefCount(0), 68c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert hardRefCount(0), 69c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert cachePtr(NULL) {} 70f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 71f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** Initializes totalRefCount, softRefCount to 0. */ 72c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert SharedObject(const SharedObject &other) : 73c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UObject(other), 74c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert totalRefCount(0), 75c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert softRefCount(0), 76c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert hardRefCount(0), 77c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert cachePtr(NULL) {} 78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius virtual ~SharedObject(); 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Increments the number of references to this object. Thread-safe. 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 84c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void addRef() const { addRef(FALSE); } 85c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 86c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 87c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Increments the number of references to this object. 88c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 89c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 90c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 91c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void addRefWhileHoldingCacheLock() const { addRef(TRUE); } 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 94c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Increments the number of soft references to this object. 95c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 96c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 97f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */ 98f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius void addSoftRef() const; 99f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 100f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** 101f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Decrements the number of references to this object. Thread-safe. 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 103c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void removeRef() const { removeRef(FALSE); } 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 106c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Decrements the number of references to this object. 107c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 108c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 109c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 110c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void removeRefWhileHoldingCacheLock() const { removeRef(TRUE); } 111c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 112c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 113c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Decrements the number of soft references to this object. 114c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 115c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 116f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */ 117f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius void removeSoftRef() const; 118f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 119f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** 120f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Returns the reference counter including soft references. 121f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Uses a memory barrier. 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t getRefCount() const; 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 125f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** 126c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Returns the count of soft references only. 127c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 128c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 129c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 130c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t getSoftRefCount() const { return softRefCount; } 131c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 132c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 133c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Returns the count of hard references only. Uses a memory barrier. 134f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Used for testing the cache. Regular clients won't need this. 135f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */ 136c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert int32_t getHardRefCount() const; 137c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 138c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 139c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * If noHardReferences() == TRUE then this object has no hard references. 140c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache. 141c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 142c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert inline UBool noHardReferences() const { return getHardRefCount() == 0; } 143f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 144f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** 145c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * If hasHardReferences() == TRUE then this object has hard references. 146c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache. 147f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */ 148c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert inline UBool hasHardReferences() const { return getHardRefCount() != 0; } 149c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 150c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 151c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * If noSoftReferences() == TRUE then this object has no soft references. 152c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called only from within the internals of UnifiedCache and 153c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * only while the cache global mutex is held. 154c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 155c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert UBool noSoftReferences() const { return (softRefCount == 0); } 156f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius 157f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius /** 158f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Deletes this object if it has no references or soft references. 159f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius */ 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void deleteIfZeroRefCount() const; 161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 163c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * @internal For UnifedCache use only to register this object with itself. 164c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Must be called before this object is exposed to multiple threads. 165c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert */ 166c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void registerWithCache(const UnifiedCacheBase *ptr) const { 167c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert cachePtr = ptr; 168c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert } 169c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 170c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert /** 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Returns a writable version of ptr. 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If there is exactly one owner, then ptr itself is returned as a 173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * non-const pointer. 174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If there are multiple owners, then ptr is replaced with a 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * copy-constructed clone, 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * and that is returned. 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Returns NULL if cloning failed. 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * T must be a subclass of SharedObject. 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static T *copyOnWrite(const T *&ptr) { 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const T *p = ptr; 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(p->getRefCount() <= 1) { return const_cast<T *>(p); } 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius T *p2 = new T(*p); 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(p2 == NULL) { return NULL; } 187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius p->removeRef(); 188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr = p2; 189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius p2->addRef(); 190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return p2; 191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Makes dest an owner of the object pointed to by src while adjusting 195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * reference counts and deleting the previous object dest pointed to 196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * if necessary. Before this call is made, dest must either be NULL or 197f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * be included in the reference count of the object it points to. 198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * T must be a subclass of SharedObject. 200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static void copyPtr(const T *src, const T *&dest) { 203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(src != dest) { 204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(dest != NULL) { dest->removeRef(); } 205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest = src; 206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(src != NULL) { src->addRef(); } 207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 211f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius * Equivalent to copyPtr(NULL, dest). 212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static void clearPtr(const T *&ptr) { 215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ptr != NULL) { 216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr->removeRef(); 217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr = NULL; 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate: 222f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius mutable u_atomic_int32_t totalRefCount; 223c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 224c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert // Any thread modifying softRefCount must hold the global cache mutex 225c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert mutable int32_t softRefCount; 226c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 227c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert mutable u_atomic_int32_t hardRefCount; 228c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert mutable const UnifiedCacheBase *cachePtr; 229c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void addRef(UBool withCacheLock) const; 230c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert void removeRef(UBool withCacheLock) const; 231c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert 232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif 237