/src/icu/icu4c/source/common/sharedobject.h
Line | Count | Source |
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 | 9 | 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 &) = delete; |
42 | | UnifiedCacheBase &operator=(const UnifiedCacheBase &) = delete; |
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_CLASS SharedObject : public UObject { |
55 | | public: |
56 | | /** Initializes totalRefCount, softRefCount to 0. */ |
57 | | U_COMMON_API SharedObject() : |
58 | 72.1k | softRefCount(0), |
59 | 72.1k | hardRefCount(0), |
60 | 72.1k | cachePtr(nullptr) {} |
61 | | |
62 | | /** Initializes totalRefCount, softRefCount to 0. */ |
63 | | U_COMMON_API SharedObject(const SharedObject &other) : |
64 | 14.5k | UObject(other), |
65 | 14.5k | softRefCount(0), |
66 | 14.5k | hardRefCount(0), |
67 | 14.5k | cachePtr(nullptr) {} |
68 | | |
69 | | U_COMMON_API 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 | | U_COMMON_API 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 | | U_COMMON_API void removeRef() const; |
85 | | |
86 | | /** |
87 | | * Returns the number of hard references for this object. |
88 | | * Uses a memory barrier. |
89 | | */ |
90 | | U_COMMON_API 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 | 102k | U_COMMON_API 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 | 0 | U_COMMON_API 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 solely responsible for eviction and deletion. |
108 | | */ |
109 | | U_COMMON_API 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 nullptr if cloning failed. |
120 | | * |
121 | | * T must be a subclass of SharedObject. |
122 | | */ |
123 | | template<typename T> |
124 | 14.6k | static T *copyOnWrite(const T *&ptr) { |
125 | 14.6k | const T *p = ptr; |
126 | 14.6k | if(p->getRefCount() <= 1) { return const_cast<T *>(p); } |
127 | 14.5k | T *p2 = new T(*p); |
128 | 14.5k | if(p2 == nullptr) { return nullptr; } |
129 | 14.5k | p->removeRef(); |
130 | 14.5k | ptr = p2; |
131 | 14.5k | p2->addRef(); |
132 | 14.5k | return p2; |
133 | 14.5k | } |
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 nullptr 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 | 473k | static void copyPtr(const T *src, const T *&dest) { |
145 | 473k | if(src != dest) { |
146 | 473k | if(dest != nullptr) { dest->removeRef(); } |
147 | 473k | dest = src; |
148 | 473k | if(src != nullptr) { src->addRef(); } |
149 | 473k | } |
150 | 473k | } void icu_78::SharedObject::copyPtr<icu_78::RelativeDateTimeCacheData>(icu_78::RelativeDateTimeCacheData const*, icu_78::RelativeDateTimeCacheData const*&) Line | Count | Source | 144 | 2.21k | static void copyPtr(const T *src, const T *&dest) { | 145 | 2.21k | if(src != dest) { | 146 | 2.21k | if(dest != nullptr) { dest->removeRef(); } | 147 | 2.21k | dest = src; | 148 | 2.21k | if(src != nullptr) { src->addRef(); } | 149 | 2.21k | } | 150 | 2.21k | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedNumberFormat>(icu_78::SharedNumberFormat const*, icu_78::SharedNumberFormat const*&) Line | Count | Source | 144 | 129k | static void copyPtr(const T *src, const T *&dest) { | 145 | 129k | if(src != dest) { | 146 | 129k | if(dest != nullptr) { dest->removeRef(); } | 147 | 129k | dest = src; | 148 | 129k | if(src != nullptr) { src->addRef(); } | 149 | 129k | } | 150 | 129k | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedPluralRules>(icu_78::SharedPluralRules const*, icu_78::SharedPluralRules const*&) Line | Count | Source | 144 | 21.0k | static void copyPtr(const T *src, const T *&dest) { | 145 | 21.0k | if(src != dest) { | 146 | 21.0k | if(dest != nullptr) { dest->removeRef(); } | 147 | 21.0k | dest = src; | 148 | 21.0k | if(src != nullptr) { src->addRef(); } | 149 | 21.0k | } | 150 | 21.0k | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedBreakIterator>(icu_78::SharedBreakIterator const*, icu_78::SharedBreakIterator const*&) Line | Count | Source | 144 | 202 | static void copyPtr(const T *src, const T *&dest) { | 145 | 202 | if(src != dest) { | 146 | 202 | if(dest != nullptr) { dest->removeRef(); } | 147 | 202 | dest = src; | 148 | 202 | if(src != nullptr) { src->addRef(); } | 149 | 202 | } | 150 | 202 | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedCalendar>(icu_78::SharedCalendar const*, icu_78::SharedCalendar const*&) Line | Count | Source | 144 | 157k | static void copyPtr(const T *src, const T *&dest) { | 145 | 157k | if(src != dest) { | 146 | 157k | if(dest != nullptr) { dest->removeRef(); } | 147 | 157k | dest = src; | 148 | 157k | if(src != nullptr) { src->addRef(); } | 149 | 157k | } | 150 | 157k | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedDateFormatSymbols>(icu_78::SharedDateFormatSymbols const*, icu_78::SharedDateFormatSymbols const*&) Line | Count | Source | 144 | 109k | static void copyPtr(const T *src, const T *&dest) { | 145 | 109k | if(src != dest) { | 146 | 109k | if(dest != nullptr) { dest->removeRef(); } | 147 | 109k | dest = src; | 148 | 109k | if(src != nullptr) { src->addRef(); } | 149 | 109k | } | 150 | 109k | } |
Unexecuted instantiation: void icu_78::SharedObject::copyPtr<icu_78::CollationSettings>(icu_78::CollationSettings const*, icu_78::CollationSettings const*&) void icu_78::SharedObject::copyPtr<icu_78::CollationCacheEntry>(icu_78::CollationCacheEntry const*, icu_78::CollationCacheEntry const*&) Line | Count | Source | 144 | 19.9k | static void copyPtr(const T *src, const T *&dest) { | 145 | 19.9k | if(src != dest) { | 146 | 19.9k | if(dest != nullptr) { dest->removeRef(); } | 147 | 19.9k | dest = src; | 148 | 19.9k | if(src != nullptr) { src->addRef(); } | 149 | 19.9k | } | 150 | 19.9k | } |
void icu_78::SharedObject::copyPtr<icu_78::SharedObject>(icu_78::SharedObject const*, icu_78::SharedObject const*&) Line | Count | Source | 144 | 322 | static void copyPtr(const T *src, const T *&dest) { | 145 | 322 | if(src != dest) { | 146 | 322 | if(dest != nullptr) { dest->removeRef(); } | 147 | 322 | dest = src; | 148 | 322 | if(src != nullptr) { src->addRef(); } | 149 | 322 | } | 150 | 322 | } |
void icu_78::SharedObject::copyPtr<icu_78::DateFmtBestPattern>(icu_78::DateFmtBestPattern const*, icu_78::DateFmtBestPattern const*&) Line | Count | Source | 144 | 32.7k | static void copyPtr(const T *src, const T *&dest) { | 145 | 32.7k | if(src != dest) { | 146 | 32.7k | if(dest != nullptr) { dest->removeRef(); } | 147 | 32.7k | dest = src; | 148 | 32.7k | if(src != nullptr) { src->addRef(); } | 149 | 32.7k | } | 150 | 32.7k | } |
|
151 | | |
152 | | /** |
153 | | * Equivalent to copyPtr(nullptr, dest). |
154 | | */ |
155 | | template<typename T> |
156 | 566k | static void clearPtr(const T *&ptr) { |
157 | 566k | if (ptr != nullptr) { |
158 | 516k | ptr->removeRef(); |
159 | 516k | ptr = nullptr; |
160 | 516k | } |
161 | 566k | } void icu_78::SharedObject::clearPtr<icu_78::RelativeDateTimeCacheData>(icu_78::RelativeDateTimeCacheData const*&) Line | Count | Source | 156 | 2.21k | static void clearPtr(const T *&ptr) { | 157 | 2.21k | if (ptr != nullptr) { | 158 | 2.21k | ptr->removeRef(); | 159 | 2.21k | ptr = nullptr; | 160 | 2.21k | } | 161 | 2.21k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedBreakIterator>(icu_78::SharedBreakIterator const*&) Line | Count | Source | 156 | 2.01k | static void clearPtr(const T *&ptr) { | 157 | 2.01k | if (ptr != nullptr) { | 158 | 0 | ptr->removeRef(); | 159 | 0 | ptr = nullptr; | 160 | 0 | } | 161 | 2.01k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedCalendar>(icu_78::SharedCalendar const*&) Line | Count | Source | 156 | 157k | static void clearPtr(const T *&ptr) { | 157 | 157k | if (ptr != nullptr) { | 158 | 157k | ptr->removeRef(); | 159 | 157k | ptr = nullptr; | 160 | 157k | } | 161 | 157k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedDateFormatSymbols>(icu_78::SharedDateFormatSymbols const*&) Line | Count | Source | 156 | 110k | static void clearPtr(const T *&ptr) { | 157 | 110k | if (ptr != nullptr) { | 158 | 109k | ptr->removeRef(); | 159 | 109k | ptr = nullptr; | 160 | 109k | } | 161 | 110k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedNumberFormat>(icu_78::SharedNumberFormat const*&) Line | Count | Source | 156 | 166k | static void clearPtr(const T *&ptr) { | 157 | 166k | if (ptr != nullptr) { | 158 | 126k | ptr->removeRef(); | 159 | 126k | ptr = nullptr; | 160 | 126k | } | 161 | 166k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedPluralRules>(icu_78::SharedPluralRules const*&) Line | Count | Source | 156 | 18.8k | static void clearPtr(const T *&ptr) { | 157 | 18.8k | if (ptr != nullptr) { | 158 | 18.8k | ptr->removeRef(); | 159 | 18.8k | ptr = nullptr; | 160 | 18.8k | } | 161 | 18.8k | } |
void icu_78::SharedObject::clearPtr<icu_78::CollationSettings>(icu_78::CollationSettings const*&) Line | Count | Source | 156 | 29.2k | static void clearPtr(const T *&ptr) { | 157 | 29.2k | if (ptr != nullptr) { | 158 | 25.6k | ptr->removeRef(); | 159 | 25.6k | ptr = nullptr; | 160 | 25.6k | } | 161 | 29.2k | } |
void icu_78::SharedObject::clearPtr<icu_78::CollationCacheEntry>(icu_78::CollationCacheEntry const*&) Line | Count | Source | 156 | 41.5k | static void clearPtr(const T *&ptr) { | 157 | 41.5k | if (ptr != nullptr) { | 158 | 37.9k | ptr->removeRef(); | 159 | 37.9k | ptr = nullptr; | 160 | 37.9k | } | 161 | 41.5k | } |
void icu_78::SharedObject::clearPtr<icu_78::CollationTailoring>(icu_78::CollationTailoring const*&) Line | Count | Source | 156 | 4.18k | static void clearPtr(const T *&ptr) { | 157 | 4.18k | if (ptr != nullptr) { | 158 | 4.18k | ptr->removeRef(); | 159 | 4.18k | ptr = nullptr; | 160 | 4.18k | } | 161 | 4.18k | } |
void icu_78::SharedObject::clearPtr<icu_78::SharedObject>(icu_78::SharedObject const*&) Line | Count | Source | 156 | 1.53k | static void clearPtr(const T *&ptr) { | 157 | 1.53k | if (ptr != nullptr) { | 158 | 1.53k | ptr->removeRef(); | 159 | 1.53k | ptr = nullptr; | 160 | 1.53k | } | 161 | 1.53k | } |
void icu_78::SharedObject::clearPtr<icu_78::DateFmtBestPattern>(icu_78::DateFmtBestPattern const*&) Line | Count | Source | 156 | 32.7k | static void clearPtr(const T *&ptr) { | 157 | 32.7k | if (ptr != nullptr) { | 158 | 32.7k | ptr->removeRef(); | 159 | 32.7k | ptr = nullptr; | 160 | 32.7k | } | 161 | 32.7k | } |
|
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 |