/src/icu/source/common/sharedobject.h
Line | Count | Source (jump to first uncovered line) |
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 | 0 | cachePtr(NULL) {} |
61 | | |
62 | | /** Initializes totalRefCount, softRefCount to 0. */ |
63 | | SharedObject(const SharedObject &other) : |
64 | | UObject(other), |
65 | | softRefCount(0), |
66 | | hardRefCount(0), |
67 | 0 | 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 | 0 | 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 | | 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 | 0 | static T *copyOnWrite(const T *&ptr) { |
125 | 0 | const T *p = ptr; |
126 | 0 | if(p->getRefCount() <= 1) { return const_cast<T *>(p); } |
127 | 0 | T *p2 = new T(*p); |
128 | 0 | if(p2 == NULL) { return NULL; } |
129 | 0 | p->removeRef(); |
130 | 0 | ptr = p2; |
131 | 0 | p2->addRef(); |
132 | 0 | return p2; |
133 | 0 | } |
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 | 0 | static void copyPtr(const T *src, const T *&dest) { |
145 | 0 | if(src != dest) { |
146 | 0 | if(dest != NULL) { dest->removeRef(); } |
147 | 0 | dest = src; |
148 | 0 | if(src != NULL) { src->addRef(); } |
149 | 0 | } |
150 | 0 | } Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::CollationCacheEntry>(icu_70::CollationCacheEntry const*, icu_70::CollationCacheEntry const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::DateFmtBestPattern>(icu_70::DateFmtBestPattern const*, icu_70::DateFmtBestPattern const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::SharedDateFormatSymbols>(icu_70::SharedDateFormatSymbols const*, icu_70::SharedDateFormatSymbols const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::CollationSettings>(icu_70::CollationSettings const*, icu_70::CollationSettings const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::SharedNumberFormat>(icu_70::SharedNumberFormat const*, icu_70::SharedNumberFormat const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::SharedCalendar>(icu_70::SharedCalendar const*, icu_70::SharedCalendar const*&) Unexecuted instantiation: void icu_70::SharedObject::copyPtr<icu_70::SharedPluralRules>(icu_70::SharedPluralRules const*, icu_70::SharedPluralRules const*&) |
151 | | |
152 | | /** |
153 | | * Equivalent to copyPtr(NULL, dest). |
154 | | */ |
155 | | template<typename T> |
156 | 0 | static void clearPtr(const T *&ptr) { |
157 | 0 | if (ptr != NULL) { |
158 | 0 | ptr->removeRef(); |
159 | 0 | ptr = NULL; |
160 | 0 | } |
161 | 0 | } Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::CollationCacheEntry>(icu_70::CollationCacheEntry const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::CollationSettings>(icu_70::CollationSettings const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::CollationTailoring>(icu_70::CollationTailoring const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::DateFmtBestPattern>(icu_70::DateFmtBestPattern const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::SharedDateFormatSymbols>(icu_70::SharedDateFormatSymbols const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::SharedNumberFormat>(icu_70::SharedNumberFormat const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::SharedCalendar>(icu_70::SharedCalendar const*&) Unexecuted instantiation: void icu_70::SharedObject::clearPtr<icu_70::SharedPluralRules>(icu_70::SharedPluralRules const*&) |
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 |