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