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