]>
Commit | Line | Data |
---|---|---|
1 | // © 2016 and later: Unicode, Inc. and others. | |
2 | // License & terms of use: http://www.unicode.org/copyright.html | |
3 | /* | |
4 | ****************************************************************************** | |
5 | * Copyright (C) 2015-2016, International Business Machines | |
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 | ||
20 | class SharedObject; | |
21 | ||
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 | /** | |
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. | |
36 | */ | |
37 | virtual void handleUnreferencedObject() const = 0; | |
38 | ||
39 | virtual ~UnifiedCacheBase(); | |
40 | private: | |
41 | UnifiedCacheBase(const UnifiedCacheBase &); | |
42 | UnifiedCacheBase &operator=(const UnifiedCacheBase &); | |
43 | }; | |
44 | ||
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: | |
56 | /** Initializes totalRefCount, softRefCount to 0. */ | |
57 | SharedObject() : | |
58 | softRefCount(0), | |
59 | hardRefCount(0), | |
60 | cachePtr(NULL) {} | |
61 | ||
62 | /** Initializes totalRefCount, softRefCount to 0. */ | |
63 | SharedObject(const SharedObject &other) : | |
64 | UObject(other), | |
65 | softRefCount(0), | |
66 | hardRefCount(0), | |
67 | cachePtr(NULL) {} | |
68 | ||
69 | virtual ~SharedObject(); | |
70 | ||
71 | /** | |
72 | * Increments the number of hard references to this object. Thread-safe. | |
73 | * Not for use from within the Unified Cache implementation. | |
74 | */ | |
75 | void addRef() const; | |
76 | ||
77 | /** | |
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. | |
83 | */ | |
84 | void removeRef() const; | |
85 | ||
86 | /** | |
87 | * Returns the number of hard references for this object. | |
88 | * Uses a memory barrier. | |
89 | */ | |
90 | int32_t getRefCount() const; | |
91 | ||
92 | /** | |
93 | * If noHardReferences() == TRUE then this object has no hard references. | |
94 | * Must be called only from within the internals of UnifiedCache. | |
95 | */ | |
96 | inline UBool noHardReferences() const { return getRefCount() == 0; } | |
97 | ||
98 | /** | |
99 | * If hasHardReferences() == TRUE then this object has hard references. | |
100 | * Must be called only from within the internals of UnifiedCache. | |
101 | */ | |
102 | inline UBool hasHardReferences() const { return getRefCount() != 0; } | |
103 | ||
104 | /** | |
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. | |
108 | */ | |
109 | void deleteIfZeroRefCount() const; | |
110 | ||
111 | ||
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 | |
139 | * be included in the reference count of the object it points to. | |
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 | /** | |
153 | * Equivalent to copyPtr(NULL, dest). | |
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: | |
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 | */ | |
170 | mutable int32_t softRefCount; | |
171 | friend class UnifiedCache; | |
172 | ||
173 | /** | |
174 | * Reference count, excluding references from within the UnifiedCache implementation. | |
175 | */ | |
176 | mutable u_atomic_int32_t hardRefCount; | |
177 | ||
178 | mutable const UnifiedCacheBase *cachePtr; | |
179 | ||
180 | }; | |
181 | ||
182 | U_NAMESPACE_END | |
183 | ||
184 | #endif |