]>
Commit | Line | Data |
---|---|---|
f3c0d7a5 A |
1 | // © 2016 and later: Unicode, Inc. and others. |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
57a6839d A |
3 | /* |
4 | ****************************************************************************** | |
2ca993e8 | 5 | * Copyright (C) 2015-2016, International Business Machines |
57a6839d A |
6 | * Corporation and others. All Rights Reserved. |
7 | ****************************************************************************** | |
8 | * sharedobject.h | |
9 | */ | |
10 | ||
11 | #ifndef __SHAREDOBJECT_H__ | |
12 | #define __SHAREDOBJECT_H__ | |
13 | ||
14 | ||
15 | #include "unicode/uobject.h" | |
16 | #include "umutex.h" | |
17 | ||
18 | U_NAMESPACE_BEGIN | |
19 | ||
0f5d89e8 A |
20 | class SharedObject; |
21 | ||
2ca993e8 A |
22 | /** |
23 | * Base class for unified cache exposing enough methods to SharedObject | |
24 | * instances to allow their addRef() and removeRef() methods to | |
25 | * update cache metrics. No other part of ICU, except for SharedObject, | |
26 | * should directly call the methods of this base class. | |
27 | */ | |
28 | class U_COMMON_API UnifiedCacheBase : public UObject { | |
29 | public: | |
30 | UnifiedCacheBase() { } | |
31 | ||
32 | /** | |
0f5d89e8 A |
33 | * Notify the cache implementation that an object was seen transitioning to |
34 | * zero hard references. The cache may use this to keep track the number of | |
35 | * unreferenced SharedObjects, and to trigger evictions. | |
2ca993e8 | 36 | */ |
0f5d89e8 | 37 | virtual void handleUnreferencedObject() const = 0; |
2ca993e8 | 38 | |
2ca993e8 A |
39 | virtual ~UnifiedCacheBase(); |
40 | private: | |
41 | UnifiedCacheBase(const UnifiedCacheBase &); | |
42 | UnifiedCacheBase &operator=(const UnifiedCacheBase &); | |
43 | }; | |
44 | ||
57a6839d A |
45 | /** |
46 | * Base class for shared, reference-counted, auto-deleted objects. | |
47 | * Subclasses can be immutable. | |
48 | * If they are mutable, then they must implement their copy constructor | |
49 | * so that copyOnWrite() works. | |
50 | * | |
51 | * Either stack-allocate, use LocalPointer, or use addRef()/removeRef(). | |
52 | * Sharing requires reference-counting. | |
53 | */ | |
54 | class U_COMMON_API SharedObject : public UObject { | |
55 | public: | |
b331163b | 56 | /** Initializes totalRefCount, softRefCount to 0. */ |
2ca993e8 | 57 | SharedObject() : |
2ca993e8 A |
58 | softRefCount(0), |
59 | hardRefCount(0), | |
60 | cachePtr(NULL) {} | |
b331163b A |
61 | |
62 | /** Initializes totalRefCount, softRefCount to 0. */ | |
2ca993e8 A |
63 | SharedObject(const SharedObject &other) : |
64 | UObject(other), | |
2ca993e8 A |
65 | softRefCount(0), |
66 | hardRefCount(0), | |
67 | cachePtr(NULL) {} | |
57a6839d | 68 | |
57a6839d A |
69 | virtual ~SharedObject(); |
70 | ||
71 | /** | |
0f5d89e8 A |
72 | * Increments the number of hard references to this object. Thread-safe. |
73 | * Not for use from within the Unified Cache implementation. | |
2ca993e8 | 74 | */ |
0f5d89e8 | 75 | void addRef() const; |
2ca993e8 A |
76 | |
77 | /** | |
0f5d89e8 A |
78 | * Decrements the number of hard references to this object, and |
79 | * arrange for possible cache-eviction and/or deletion if ref | |
80 | * count goes to zero. Thread-safe. | |
81 | * | |
82 | * Not for use from within the UnifiedCache implementation. | |
b331163b | 83 | */ |
0f5d89e8 | 84 | void removeRef() const; |
b331163b A |
85 | |
86 | /** | |
0f5d89e8 | 87 | * Returns the number of hard references for this object. |
b331163b | 88 | * Uses a memory barrier. |
57a6839d A |
89 | */ |
90 | int32_t getRefCount() const; | |
91 | ||
2ca993e8 A |
92 | /** |
93 | * If noHardReferences() == TRUE then this object has no hard references. | |
94 | * Must be called only from within the internals of UnifiedCache. | |
95 | */ | |
0f5d89e8 | 96 | inline UBool noHardReferences() const { return getRefCount() == 0; } |
b331163b A |
97 | |
98 | /** | |
2ca993e8 A |
99 | * If hasHardReferences() == TRUE then this object has hard references. |
100 | * Must be called only from within the internals of UnifiedCache. | |
b331163b | 101 | */ |
0f5d89e8 | 102 | inline UBool hasHardReferences() const { return getRefCount() != 0; } |
2ca993e8 A |
103 | |
104 | /** | |
0f5d89e8 A |
105 | * Deletes this object if it has no references. |
106 | * Available for non-cached SharedObjects only. Ownership of cached objects | |
107 | * is with the UnifiedCache, which is soley responsible for eviction and deletion. | |
b331163b | 108 | */ |
57a6839d A |
109 | void deleteIfZeroRefCount() const; |
110 | ||
2ca993e8 | 111 | |
57a6839d A |
112 | /** |
113 | * Returns a writable version of ptr. | |
114 | * If there is exactly one owner, then ptr itself is returned as a | |
115 | * non-const pointer. | |
116 | * If there are multiple owners, then ptr is replaced with a | |
117 | * copy-constructed clone, | |
118 | * and that is returned. | |
119 | * Returns NULL if cloning failed. | |
120 | * | |
121 | * T must be a subclass of SharedObject. | |
122 | */ | |
123 | template<typename T> | |
124 | static T *copyOnWrite(const T *&ptr) { | |
125 | const T *p = ptr; | |
126 | if(p->getRefCount() <= 1) { return const_cast<T *>(p); } | |
127 | T *p2 = new T(*p); | |
128 | if(p2 == NULL) { return NULL; } | |
129 | p->removeRef(); | |
130 | ptr = p2; | |
131 | p2->addRef(); | |
132 | return p2; | |
133 | } | |
134 | ||
135 | /** | |
136 | * Makes dest an owner of the object pointed to by src while adjusting | |
137 | * reference counts and deleting the previous object dest pointed to | |
138 | * if necessary. Before this call is made, dest must either be NULL or | |
b331163b | 139 | * be included in the reference count of the object it points to. |
57a6839d A |
140 | * |
141 | * T must be a subclass of SharedObject. | |
142 | */ | |
143 | template<typename T> | |
144 | static void copyPtr(const T *src, const T *&dest) { | |
145 | if(src != dest) { | |
146 | if(dest != NULL) { dest->removeRef(); } | |
147 | dest = src; | |
148 | if(src != NULL) { src->addRef(); } | |
149 | } | |
150 | } | |
151 | ||
152 | /** | |
b331163b | 153 | * Equivalent to copyPtr(NULL, dest). |
57a6839d A |
154 | */ |
155 | template<typename T> | |
156 | static void clearPtr(const T *&ptr) { | |
157 | if (ptr != NULL) { | |
158 | ptr->removeRef(); | |
159 | ptr = NULL; | |
160 | } | |
161 | } | |
162 | ||
163 | private: | |
0f5d89e8 A |
164 | /** |
165 | * The number of references from the UnifiedCache, which is | |
166 | * the number of times that the sharedObject is stored as a hash table value. | |
167 | * For use by UnifiedCache implementation code only. | |
168 | * All access is synchronized by UnifiedCache's gCacheMutex | |
169 | */ | |
2ca993e8 | 170 | mutable int32_t softRefCount; |
0f5d89e8 | 171 | friend class UnifiedCache; |
2ca993e8 | 172 | |
0f5d89e8 A |
173 | /** |
174 | * Reference count, excluding references from within the UnifiedCache implementation. | |
175 | */ | |
2ca993e8 | 176 | mutable u_atomic_int32_t hardRefCount; |
0f5d89e8 | 177 | |
2ca993e8 | 178 | mutable const UnifiedCacheBase *cachePtr; |
2ca993e8 | 179 | |
57a6839d A |
180 | }; |
181 | ||
182 | U_NAMESPACE_END | |
183 | ||
184 | #endif |