]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/unifiedcache.h
ICU-551.24.tar.gz
[apple/icu.git] / icuSources / common / unifiedcache.h
CommitLineData
b331163b
A
1/*
2******************************************************************************
3* Copyright (C) 2014, International Business Machines Corporation and
4* others. All Rights Reserved.
5******************************************************************************
6*
7* File UNIFIEDCACHE.H - The ICU Unified cache.
8******************************************************************************
9*/
10
11#ifndef __UNIFIED_CACHE_H__
12#define __UNIFIED_CACHE_H__
13
14#include "utypeinfo.h" // for 'typeid' to work
15
16#include "unicode/uobject.h"
17#include "unicode/locid.h"
18#include "sharedobject.h"
19#include "unicode/unistr.h"
20#include "cstring.h"
21#include "ustr_imp.h"
22
23struct UHashtable;
24struct UHashElement;
25
26U_NAMESPACE_BEGIN
27
28class UnifiedCache;
29
30/**
31 * A base class for all cache keys
32 */
33class U_COMMON_API CacheKeyBase : public UObject {
34 public:
35 CacheKeyBase() : creationStatus(U_ZERO_ERROR) {}
36
37 /**
38 * Copy constructor. Needed to support cloning.
39 */
40 CacheKeyBase(const CacheKeyBase &other)
41 : UObject(other), creationStatus(other.creationStatus) { }
42 virtual ~CacheKeyBase();
43
44 /**
45 * Returns the hash code for this object.
46 */
47 virtual int32_t hashCode() const = 0;
48
49 /**
50 * Clones this object polymorphically. Caller owns returned value.
51 */
52 virtual CacheKeyBase *clone() const = 0;
53
54 /**
55 * Equality operator.
56 */
57 virtual UBool operator == (const CacheKeyBase &other) const = 0;
58
59 /**
60 * Create a new object for this key. Called by cache on cache miss.
61 * createObject must add a reference to the object it returns. Note
62 * that getting an object from the cache and returning it without calling
63 * removeRef on it satisfies this requirement. It can also return NULL
64 * and set status to an error.
65 *
66 * @param creationContext the context in which the object is being
67 * created. May be NULL.
68 * @param status Implementations can return a failure here.
69 * In addition, implementations may return a
70 * non NULL object and set a warning status.
71 */
72 virtual const SharedObject *createObject(
73 const void *creationContext, UErrorCode &status) const = 0;
74
75 /**
76 * Writes a description of this key to buffer and returns buffer. Written
77 * description is NULL terminated.
78 */
79 virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0;
80
81 /**
82 * Inequality operator.
83 */
84 UBool operator != (const CacheKeyBase &other) const {
85 return !(*this == other);
86 }
87 private:
88 mutable UErrorCode creationStatus;
89 friend class UnifiedCache;
90};
91
92
93
94/**
95 * Templated version of CacheKeyBase.
96 * A key of type LocaleCacheKey<T> maps to a value of type T.
97 */
98template<typename T>
99class CacheKey : public CacheKeyBase {
100 public:
101 virtual ~CacheKey() { }
102 /**
103 * The template parameter, T, determines the hash code returned.
104 */
105 virtual int32_t hashCode() const {
106 const char *s = typeid(T).name();
107 return ustr_hashCharsN(s, uprv_strlen(s));
108 }
109
110 /**
111 * Use the value type, T, as the description.
112 */
113 virtual char *writeDescription(char *buffer, int32_t bufLen) const {
114 const char *s = typeid(T).name();
115 uprv_strncpy(buffer, s, bufLen);
116 buffer[bufLen - 1] = 0;
117 return buffer;
118 }
119
120 /**
121 * Two objects are equal if they are of the same type.
122 */
123 virtual UBool operator == (const CacheKeyBase &other) const {
124 return typeid(*this) == typeid(other);
125 }
126};
127
128/**
129 * Cache key based on locale.
130 * A key of type LocaleCacheKey<T> maps to a value of type T.
131 */
132template<typename T>
133class LocaleCacheKey : public CacheKey<T> {
134 protected:
135 Locale fLoc;
136 public:
137 LocaleCacheKey(const Locale &loc) : fLoc(loc) {};
138 LocaleCacheKey(const LocaleCacheKey<T> &other)
139 : CacheKey<T>(other), fLoc(other.fLoc) { }
140 virtual ~LocaleCacheKey() { }
141 virtual int32_t hashCode() const {
142 return 37 *CacheKey<T>::hashCode() + fLoc.hashCode();
143 }
144 virtual UBool operator == (const CacheKeyBase &other) const {
145 // reflexive
146 if (this == &other) {
147 return TRUE;
148 }
149 if (!CacheKey<T>::operator == (other)) {
150 return FALSE;
151 }
152 // We know this and other are of same class because operator== on
153 // CacheKey returned true.
154 const LocaleCacheKey<T> *fOther =
155 static_cast<const LocaleCacheKey<T> *>(&other);
156 return fLoc == fOther->fLoc;
157 }
158 virtual CacheKeyBase *clone() const {
159 return new LocaleCacheKey<T>(*this);
160 }
161 virtual const T *createObject(
162 const void *creationContext, UErrorCode &status) const;
163 /**
164 * Use the locale id as the description.
165 */
166 virtual char *writeDescription(char *buffer, int32_t bufLen) const {
167 const char *s = fLoc.getName();
168 uprv_strncpy(buffer, s, bufLen);
169 buffer[bufLen - 1] = 0;
170 return buffer;
171 }
172
173};
174
175/**
176 * The unified cache. A singleton type.
177 */
178class U_COMMON_API UnifiedCache : public UObject {
179 public:
180 /**
181 * @internal
182 */
183 UnifiedCache(UErrorCode &status);
184
185 /**
186 * Returns the cache instance.
187 */
188 static const UnifiedCache *getInstance(UErrorCode &status);
189
190 /**
191 * Fetches a value from the cache by key. Equivalent to
192 * get(key, NULL, ptr, status);
193 */
194 template<typename T>
195 void get(
196 const CacheKey<T>& key,
197 const T *&ptr,
198 UErrorCode &status) const {
199 get(key, NULL, ptr, status);
200 }
201
202 /**
203 * Fetches value from the cache by key.
204 *
205 * @param key the cache key.
206 * @param creationContext passed verbatim to createObject method of key
207 * @param ptr On entry, ptr must be NULL or be included if
208 * the reference count of the object it points
209 * to. On exit, ptr points to the fetched object
210 * from the cache or is left unchanged on
211 * failure. Caller must call removeRef on ptr
212 * if set to a non NULL value.
213 * @param status Any error returned here. May be set to a
214 * warning value even if ptr is set.
215 */
216 template<typename T>
217 void get(
218 const CacheKey<T>& key,
219 const void *creationContext,
220 const T *&ptr,
221 UErrorCode &status) const {
222 if (U_FAILURE(status)) {
223 return;
224 }
225 UErrorCode creationStatus = U_ZERO_ERROR;
226 const SharedObject *value = NULL;
227 _get(key, value, creationContext, creationStatus);
228 const T *tvalue = (const T *) value;
229 if (U_SUCCESS(creationStatus)) {
230 SharedObject::copyPtr(tvalue, ptr);
231 }
232 SharedObject::clearPtr(tvalue);
233 // Take care not to overwrite a warning status passed in with
234 // another warning or U_ZERO_ERROR.
235 if (status == U_ZERO_ERROR || U_FAILURE(creationStatus)) {
236 status = creationStatus;
237 }
238 }
239
240#ifdef UNIFIED_CACHE_DEBUG
241 /**
242 * Dumps the contents of this cache to standard error. Used for testing of
243 * cache only.
244 */
245 void dumpContents() const;
246#endif
247
248 /**
249 * Convenience method to get a value of type T from cache for a
250 * particular locale with creationContext == NULL.
251 * @param loc the locale
252 * @param ptr On entry, must be NULL or included in the ref count
253 * of the object to which it points.
254 * On exit, fetched value stored here or is left
255 * unchanged on failure. Caller must call removeRef on
256 * ptr if set to a non NULL value.
257 * @param status Any error returned here. May be set to a
258 * warning value even if ptr is set.
259 */
260 template<typename T>
261 static void getByLocale(
262 const Locale &loc, const T *&ptr, UErrorCode &status) {
263 const UnifiedCache *cache = getInstance(status);
264 if (U_FAILURE(status)) {
265 return;
266 }
267 cache->get(LocaleCacheKey<T>(loc), ptr, status);
268 }
269
270#ifdef UNIFIED_CACHE_DEBUG
271 /**
272 * Dumps the cache contents to stderr. For testing only.
273 */
274 static void dump();
275#endif
276
277 /**
278 * Returns the number of keys in this cache. For testing only.
279 */
280 int32_t keyCount() const;
281
282 /**
283 * Removes any values from cache that are not referenced outside
284 * the cache.
285 */
286 void flush() const;
287
288 virtual ~UnifiedCache();
289 private:
290 UHashtable *fHashtable;
291 UnifiedCache(const UnifiedCache &other);
292 UnifiedCache &operator=(const UnifiedCache &other);
293 UBool _flush(UBool all) const;
294 void _get(
295 const CacheKeyBase &key,
296 const SharedObject *&value,
297 const void *creationContext,
298 UErrorCode &status) const;
299 UBool _poll(
300 const CacheKeyBase &key,
301 const SharedObject *&value,
302 UErrorCode &status) const;
303 void _putNew(
304 const CacheKeyBase &key,
305 const SharedObject *value,
306 const UErrorCode creationStatus,
307 UErrorCode &status) const;
308 void _putIfAbsentAndGet(
309 const CacheKeyBase &key,
310 const SharedObject *&value,
311 UErrorCode &status) const;
312#ifdef UNIFIED_CACHE_DEBUG
313 void _dumpContents() const;
314#endif
315 static void _put(
316 const UHashElement *element,
317 const SharedObject *value,
318 const UErrorCode status);
319 static void _fetch(
320 const UHashElement *element,
321 const SharedObject *&value,
322 UErrorCode &status);
323 static UBool _inProgress(const UHashElement *element);
324};
325
326U_NAMESPACE_END
327
328#endif