OLD | NEW |
1 /* | 1 /* |
2 ****************************************************************************** | 2 ****************************************************************************** |
3 * Copyright (C) 2014, International Business Machines Corporation and | 3 * Copyright (C) 2015, International Business Machines Corporation and |
4 * others. All Rights Reserved. | 4 * others. All Rights Reserved. |
5 ****************************************************************************** | 5 ****************************************************************************** |
6 * | 6 * |
7 * File UNIFIEDCACHE.H - The ICU Unified cache. | 7 * File UNIFIEDCACHE.H - The ICU Unified cache. |
8 ****************************************************************************** | 8 ****************************************************************************** |
9 */ | 9 */ |
10 | 10 |
11 #ifndef __UNIFIED_CACHE_H__ | 11 #ifndef __UNIFIED_CACHE_H__ |
12 #define __UNIFIED_CACHE_H__ | 12 #define __UNIFIED_CACHE_H__ |
13 | 13 |
14 #include "utypeinfo.h" // for 'typeid' to work | 14 #include "utypeinfo.h" // for 'typeid' to work |
15 | 15 |
16 #include "unicode/uobject.h" | 16 #include "unicode/uobject.h" |
17 #include "unicode/locid.h" | 17 #include "unicode/locid.h" |
18 #include "sharedobject.h" | 18 #include "sharedobject.h" |
19 #include "unicode/unistr.h" | 19 #include "unicode/unistr.h" |
20 #include "cstring.h" | 20 #include "cstring.h" |
21 #include "ustr_imp.h" | 21 #include "ustr_imp.h" |
22 | 22 |
23 struct UHashtable; | 23 struct UHashtable; |
24 struct UHashElement; | 24 struct UHashElement; |
25 | 25 |
26 U_NAMESPACE_BEGIN | 26 U_NAMESPACE_BEGIN |
27 | 27 |
28 class UnifiedCache; | 28 class UnifiedCache; |
29 | 29 |
30 /** | 30 /** |
31 * A base class for all cache keys | 31 * A base class for all cache keys. |
32 */ | 32 */ |
33 class U_COMMON_API CacheKeyBase : public UObject { | 33 class U_COMMON_API CacheKeyBase : public UObject { |
34 public: | 34 public: |
35 CacheKeyBase() : creationStatus(U_ZERO_ERROR) {} | 35 CacheKeyBase() : fCreationStatus(U_ZERO_ERROR), fIsMaster(FALSE) {} |
36 | 36 |
37 /** | 37 /** |
38 * Copy constructor. Needed to support cloning. | 38 * Copy constructor. Needed to support cloning. |
39 */ | 39 */ |
40 CacheKeyBase(const CacheKeyBase &other) | 40 CacheKeyBase(const CacheKeyBase &other) |
41 : UObject(other), creationStatus(other.creationStatus) { } | 41 : UObject(other), fCreationStatus(other.fCreationStatus), fIsMaster(F
ALSE) { } |
42 virtual ~CacheKeyBase(); | 42 virtual ~CacheKeyBase(); |
43 | 43 |
44 /** | 44 /** |
45 * Returns the hash code for this object. | 45 * Returns the hash code for this object. |
46 */ | 46 */ |
47 virtual int32_t hashCode() const = 0; | 47 virtual int32_t hashCode() const = 0; |
48 | 48 |
49 /** | 49 /** |
50 * Clones this object polymorphically. Caller owns returned value. | 50 * Clones this object polymorphically. Caller owns returned value. |
51 */ | 51 */ |
(...skipping 26 matching lines...) Expand all Loading... |
78 */ | 78 */ |
79 virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0; | 79 virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0; |
80 | 80 |
81 /** | 81 /** |
82 * Inequality operator. | 82 * Inequality operator. |
83 */ | 83 */ |
84 UBool operator != (const CacheKeyBase &other) const { | 84 UBool operator != (const CacheKeyBase &other) const { |
85 return !(*this == other); | 85 return !(*this == other); |
86 } | 86 } |
87 private: | 87 private: |
88 mutable UErrorCode creationStatus; | 88 mutable UErrorCode fCreationStatus; |
| 89 mutable UBool fIsMaster; |
89 friend class UnifiedCache; | 90 friend class UnifiedCache; |
90 }; | 91 }; |
91 | 92 |
92 | 93 |
93 | 94 |
94 /** | 95 /** |
95 * Templated version of CacheKeyBase. | 96 * Templated version of CacheKeyBase. |
96 * A key of type LocaleCacheKey<T> maps to a value of type T. | 97 * A key of type LocaleCacheKey<T> maps to a value of type T. |
97 */ | 98 */ |
98 template<typename T> | 99 template<typename T> |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
167 const char *s = fLoc.getName(); | 168 const char *s = fLoc.getName(); |
168 uprv_strncpy(buffer, s, bufLen); | 169 uprv_strncpy(buffer, s, bufLen); |
169 buffer[bufLen - 1] = 0; | 170 buffer[bufLen - 1] = 0; |
170 return buffer; | 171 return buffer; |
171 } | 172 } |
172 | 173 |
173 }; | 174 }; |
174 | 175 |
175 /** | 176 /** |
176 * The unified cache. A singleton type. | 177 * The unified cache. A singleton type. |
| 178 * Design doc here: |
| 179 * https://docs.google.com/document/d/1RwGQJs4N4tawNbf809iYDRCvXoMKqDJihxzYt1ysm
d8/edit?usp=sharing |
177 */ | 180 */ |
178 class U_COMMON_API UnifiedCache : public UObject { | 181 class U_COMMON_API UnifiedCache : public UnifiedCacheBase { |
179 public: | 182 public: |
180 /** | 183 /** |
181 * @internal | 184 * @internal |
| 185 * Do not call directly. Instead use UnifiedCache::getInstance() as |
| 186 * there should be only one UnifiedCache in an application. |
182 */ | 187 */ |
183 UnifiedCache(UErrorCode &status); | 188 UnifiedCache(UErrorCode &status); |
184 | 189 |
185 /** | 190 /** |
186 * Returns the cache instance. | 191 * Returns the cache instance. |
187 */ | 192 */ |
188 static const UnifiedCache *getInstance(UErrorCode &status); | 193 static UnifiedCache *getInstance(UErrorCode &status); |
189 | 194 |
190 /** | 195 /** |
191 * Fetches a value from the cache by key. Equivalent to | 196 * Fetches a value from the cache by key. Equivalent to |
192 * get(key, NULL, ptr, status); | 197 * get(key, NULL, ptr, status); |
193 */ | 198 */ |
194 template<typename T> | 199 template<typename T> |
195 void get( | 200 void get( |
196 const CacheKey<T>& key, | 201 const CacheKey<T>& key, |
197 const T *&ptr, | 202 const T *&ptr, |
198 UErrorCode &status) const { | 203 UErrorCode &status) const { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 * Returns the number of keys in this cache. For testing only. | 283 * Returns the number of keys in this cache. For testing only. |
279 */ | 284 */ |
280 int32_t keyCount() const; | 285 int32_t keyCount() const; |
281 | 286 |
282 /** | 287 /** |
283 * Removes any values from cache that are not referenced outside | 288 * Removes any values from cache that are not referenced outside |
284 * the cache. | 289 * the cache. |
285 */ | 290 */ |
286 void flush() const; | 291 void flush() const; |
287 | 292 |
| 293 /** |
| 294 * Configures at what point evcition of unused entries will begin. |
| 295 * Eviction is triggered whenever the number of unused entries exeeds |
| 296 * BOTH count AND (number of in-use items) * (percentageOfInUseItems / 100). |
| 297 * Once the number of unused entries drops below one of these, |
| 298 * eviction ceases. Because eviction happens incrementally, |
| 299 * the actual unused entry count may exceed both these numbers |
| 300 * from time to time. |
| 301 * |
| 302 * A cache entry is defined as unused if it is not essential to guarantee |
| 303 * that for a given key X, the cache returns the same reference to the |
| 304 * same value as long as the client already holds a reference to that |
| 305 * value. |
| 306 * |
| 307 * If this method is never called, the default settings are 1000 and 100%. |
| 308 * |
| 309 * Although this method is thread-safe, it is designed to be called at |
| 310 * application startup. If it is called in the middle of execution, it |
| 311 * will have no immediate effect on the cache. However over time, the |
| 312 * cache will perform eviction slices in an attempt to honor the new |
| 313 * settings. |
| 314 * |
| 315 * If a client already holds references to many different unique values |
| 316 * in the cache such that the number of those unique values far exeeds |
| 317 * "count" then the cache may not be able to maintain this maximum. |
| 318 * However, if this happens, the cache still guarantees that the number of |
| 319 * unused entries will remain only a small percentage of the total cache |
| 320 * size. |
| 321 * |
| 322 * If the parameters passed are negative, setEvctionPolicy sets status to |
| 323 * U_ILLEGAL_ARGUMENT_ERROR. |
| 324 */ |
| 325 void setEvictionPolicy( |
| 326 int32_t count, int32_t percentageOfInUseItems, UErrorCode &status); |
| 327 |
| 328 |
| 329 /** |
| 330 * Returns how many entries have been auto evicted during the lifetime |
| 331 * of this cache. This only includes auto evicted entries, not |
| 332 * entries evicted because of a call to flush(). |
| 333 */ |
| 334 int64_t autoEvictedCount() const; |
| 335 |
| 336 /** |
| 337 * Returns the unused entry count in this cache. For testing only, |
| 338 * Regular clients will not need this. |
| 339 */ |
| 340 int32_t unusedCount() const; |
| 341 |
| 342 virtual void incrementItemsInUse() const; |
| 343 virtual void decrementItemsInUseWithLockingAndEviction() const; |
| 344 virtual void decrementItemsInUse() const; |
288 virtual ~UnifiedCache(); | 345 virtual ~UnifiedCache(); |
289 private: | 346 private: |
290 UHashtable *fHashtable; | 347 UHashtable *fHashtable; |
| 348 mutable int32_t fEvictPos; |
| 349 mutable int32_t fItemsInUseCount; |
| 350 int32_t fMaxUnused; |
| 351 int32_t fMaxPercentageOfInUse; |
| 352 mutable int64_t fAutoEvictedCount; |
291 UnifiedCache(const UnifiedCache &other); | 353 UnifiedCache(const UnifiedCache &other); |
292 UnifiedCache &operator=(const UnifiedCache &other); | 354 UnifiedCache &operator=(const UnifiedCache &other); |
293 UBool _flush(UBool all) const; | 355 UBool _flush(UBool all) const; |
294 void _get( | 356 void _get( |
295 const CacheKeyBase &key, | 357 const CacheKeyBase &key, |
296 const SharedObject *&value, | 358 const SharedObject *&value, |
297 const void *creationContext, | 359 const void *creationContext, |
298 UErrorCode &status) const; | 360 UErrorCode &status) const; |
299 UBool _poll( | 361 UBool _poll( |
300 const CacheKeyBase &key, | 362 const CacheKeyBase &key, |
301 const SharedObject *&value, | 363 const SharedObject *&value, |
302 UErrorCode &status) const; | 364 UErrorCode &status) const; |
303 void _putNew( | 365 void _putNew( |
304 const CacheKeyBase &key, | 366 const CacheKeyBase &key, |
305 const SharedObject *value, | 367 const SharedObject *value, |
306 const UErrorCode creationStatus, | 368 const UErrorCode creationStatus, |
307 UErrorCode &status) const; | 369 UErrorCode &status) const; |
308 void _putIfAbsentAndGet( | 370 void _putIfAbsentAndGet( |
309 const CacheKeyBase &key, | 371 const CacheKeyBase &key, |
310 const SharedObject *&value, | 372 const SharedObject *&value, |
311 UErrorCode &status) const; | 373 UErrorCode &status) const; |
| 374 const UHashElement *_nextElement() const; |
| 375 int32_t _computeCountOfItemsToEvict() const; |
| 376 void _runEvictionSlice() const; |
| 377 void _registerMaster( |
| 378 const CacheKeyBase *theKey, const SharedObject *value) const; |
| 379 void _put( |
| 380 const UHashElement *element, |
| 381 const SharedObject *value, |
| 382 const UErrorCode status) const; |
312 #ifdef UNIFIED_CACHE_DEBUG | 383 #ifdef UNIFIED_CACHE_DEBUG |
313 void _dumpContents() const; | 384 void _dumpContents() const; |
314 #endif | 385 #endif |
315 static void _put( | 386 static void copyPtr(const SharedObject *src, const SharedObject *&dest); |
316 const UHashElement *element, | 387 static void clearPtr(const SharedObject *&ptr); |
317 const SharedObject *value, | |
318 const UErrorCode status); | |
319 static void _fetch( | 388 static void _fetch( |
320 const UHashElement *element, | 389 const UHashElement *element, |
321 const SharedObject *&value, | 390 const SharedObject *&value, |
322 UErrorCode &status); | 391 UErrorCode &status); |
323 static UBool _inProgress(const UHashElement *element); | 392 static UBool _inProgress(const UHashElement *element); |
| 393 static UBool _inProgress( |
| 394 const SharedObject *theValue, UErrorCode creationStatus); |
| 395 static UBool _isEvictable(const UHashElement *element); |
324 }; | 396 }; |
325 | 397 |
326 U_NAMESPACE_END | 398 U_NAMESPACE_END |
327 | 399 |
328 #endif | 400 #endif |
OLD | NEW |