| 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, International Business Machines Corporation and | 
|---|
| 6 | * others. All Rights Reserved. | 
|---|
| 7 | ****************************************************************************** | 
|---|
| 8 | * | 
|---|
| 9 | * File UNIFIEDCACHE.H - The ICU Unified cache. | 
|---|
| 10 | ****************************************************************************** | 
|---|
| 11 | */ | 
|---|
| 12 |  | 
|---|
| 13 | #ifndef __UNIFIED_CACHE_H__ | 
|---|
| 14 | #define __UNIFIED_CACHE_H__ | 
|---|
| 15 |  | 
|---|
| 16 | #include "utypeinfo.h"  // for 'typeid' to work | 
|---|
| 17 |  | 
|---|
| 18 | #include "unicode/uobject.h" | 
|---|
| 19 | #include "unicode/locid.h" | 
|---|
| 20 | #include "sharedobject.h" | 
|---|
| 21 | #include "unicode/unistr.h" | 
|---|
| 22 | #include "cstring.h" | 
|---|
| 23 | #include "ustr_imp.h" | 
|---|
| 24 |  | 
|---|
| 25 | struct UHashtable; | 
|---|
| 26 | struct UHashElement; | 
|---|
| 27 |  | 
|---|
| 28 | U_NAMESPACE_BEGIN | 
|---|
| 29 |  | 
|---|
| 30 | class UnifiedCache; | 
|---|
| 31 |  | 
|---|
| 32 | /** | 
|---|
| 33 | * A base class for all cache keys. | 
|---|
| 34 | */ | 
|---|
| 35 | class U_COMMON_API CacheKeyBase : public UObject { | 
|---|
| 36 | public: | 
|---|
| 37 | CacheKeyBase() : fCreationStatus(U_ZERO_ERROR), fIsPrimary(false) {} | 
|---|
| 38 |  | 
|---|
| 39 | /** | 
|---|
| 40 | * Copy constructor. Needed to support cloning. | 
|---|
| 41 | */ | 
|---|
| 42 | CacheKeyBase(const CacheKeyBase &other) | 
|---|
| 43 | : UObject(other), fCreationStatus(other.fCreationStatus), fIsPrimary(false) { } | 
|---|
| 44 | virtual ~CacheKeyBase(); | 
|---|
| 45 |  | 
|---|
| 46 | /** | 
|---|
| 47 | * Returns the hash code for this object. | 
|---|
| 48 | */ | 
|---|
| 49 | virtual int32_t hashCode() const = 0; | 
|---|
| 50 |  | 
|---|
| 51 | /** | 
|---|
| 52 | * Clones this object polymorphically. Caller owns returned value. | 
|---|
| 53 | */ | 
|---|
| 54 | virtual CacheKeyBase *clone() const = 0; | 
|---|
| 55 |  | 
|---|
| 56 | /** | 
|---|
| 57 | * Create a new object for this key. Called by cache on cache miss. | 
|---|
| 58 | * createObject must add a reference to the object it returns. Note | 
|---|
| 59 | * that getting an object from the cache and returning it without calling | 
|---|
| 60 | * removeRef on it satisfies this requirement. It can also return nullptr | 
|---|
| 61 | * and set status to an error. | 
|---|
| 62 | * | 
|---|
| 63 | * @param creationContext the context in which the object is being | 
|---|
| 64 | *                        created. May be nullptr. | 
|---|
| 65 | * @param status          Implementations can return a failure here. | 
|---|
| 66 | *                        In addition, implementations may return a | 
|---|
| 67 | *                        non nullptr object and set a warning status. | 
|---|
| 68 | */ | 
|---|
| 69 | virtual const SharedObject *createObject( | 
|---|
| 70 | const void *creationContext, UErrorCode &status) const = 0; | 
|---|
| 71 |  | 
|---|
| 72 | /** | 
|---|
| 73 | * Writes a description of this key to buffer and returns buffer. Written | 
|---|
| 74 | * description is nullptr terminated. | 
|---|
| 75 | */ | 
|---|
| 76 | virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0; | 
|---|
| 77 |  | 
|---|
| 78 | friend inline bool operator==(const CacheKeyBase& lhs, | 
|---|
| 79 | const CacheKeyBase& rhs) { | 
|---|
| 80 | return lhs.equals(rhs); | 
|---|
| 81 | } | 
|---|
| 82 |  | 
|---|
| 83 | friend inline bool operator!=(const CacheKeyBase& lhs, | 
|---|
| 84 | const CacheKeyBase& rhs) { | 
|---|
| 85 | return !lhs.equals(rhs); | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | protected: | 
|---|
| 89 | virtual bool equals(const CacheKeyBase& other) const = 0; | 
|---|
| 90 |  | 
|---|
| 91 | private: | 
|---|
| 92 | mutable UErrorCode fCreationStatus; | 
|---|
| 93 | mutable UBool fIsPrimary; | 
|---|
| 94 | friend class UnifiedCache; | 
|---|
| 95 | }; | 
|---|
| 96 |  | 
|---|
| 97 |  | 
|---|
| 98 |  | 
|---|
| 99 | /** | 
|---|
| 100 | * Templated version of CacheKeyBase. | 
|---|
| 101 | * A key of type LocaleCacheKey<T> maps to a value of type T. | 
|---|
| 102 | */ | 
|---|
| 103 | template<typename T> | 
|---|
| 104 | class CacheKey : public CacheKeyBase { | 
|---|
| 105 | public: | 
|---|
| 106 | virtual ~CacheKey() { } | 
|---|
| 107 | /** | 
|---|
| 108 | * The template parameter, T, determines the hash code returned. | 
|---|
| 109 | */ | 
|---|
| 110 | virtual int32_t hashCode() const override { | 
|---|
| 111 | const char *s = typeid(T).name(); | 
|---|
| 112 | return ustr_hashCharsN(s, static_cast<int32_t>(uprv_strlen(s))); | 
|---|
| 113 | } | 
|---|
| 114 |  | 
|---|
| 115 | /** | 
|---|
| 116 | * Use the value type, T,  as the description. | 
|---|
| 117 | */ | 
|---|
| 118 | virtual char *writeDescription(char *buffer, int32_t bufLen) const override { | 
|---|
| 119 | const char *s = typeid(T).name(); | 
|---|
| 120 | uprv_strncpy(buffer, s, bufLen); | 
|---|
| 121 | buffer[bufLen - 1] = 0; | 
|---|
| 122 | return buffer; | 
|---|
| 123 | } | 
|---|
| 124 |  | 
|---|
| 125 | protected: | 
|---|
| 126 | /** | 
|---|
| 127 | * Two objects are equal if they are of the same type. | 
|---|
| 128 | */ | 
|---|
| 129 | virtual bool equals(const CacheKeyBase &other) const override { | 
|---|
| 130 | return this == &other || typeid(*this) == typeid(other); | 
|---|
| 131 | } | 
|---|
| 132 | }; | 
|---|
| 133 |  | 
|---|
| 134 | /** | 
|---|
| 135 | * Cache key based on locale. | 
|---|
| 136 | * A key of type LocaleCacheKey<T> maps to a value of type T. | 
|---|
| 137 | */ | 
|---|
| 138 | template<typename T> | 
|---|
| 139 | class LocaleCacheKey : public CacheKey<T> { | 
|---|
| 140 | protected: | 
|---|
| 141 | Locale   fLoc; | 
|---|
| 142 | virtual bool equals(const CacheKeyBase &other) const override { | 
|---|
| 143 | if (!CacheKey<T>::equals(other)) { | 
|---|
| 144 | return false; | 
|---|
| 145 | } | 
|---|
| 146 | // We know this and other are of same class because equals() on | 
|---|
| 147 | // CacheKey returned true. | 
|---|
| 148 | return operator==(static_cast<const LocaleCacheKey<T> &>(other)); | 
|---|
| 149 | } | 
|---|
| 150 | public: | 
|---|
| 151 | LocaleCacheKey(const Locale &loc) : fLoc(loc) {} | 
|---|
| 152 | LocaleCacheKey(const LocaleCacheKey<T> &other) | 
|---|
| 153 | : CacheKey<T>(other), fLoc(other.fLoc) { } | 
|---|
| 154 | virtual ~LocaleCacheKey() { } | 
|---|
| 155 | virtual int32_t hashCode() const override { | 
|---|
| 156 | return (int32_t)(37u * (uint32_t)CacheKey<T>::hashCode() + (uint32_t)fLoc.hashCode()); | 
|---|
| 157 | } | 
|---|
| 158 | inline bool operator == (const LocaleCacheKey<T> &other) const { | 
|---|
| 159 | return fLoc == other.fLoc; | 
|---|
| 160 | } | 
|---|
| 161 | virtual CacheKeyBase *clone() const override { | 
|---|
| 162 | return new LocaleCacheKey<T>(*this); | 
|---|
| 163 | } | 
|---|
| 164 | virtual const T *createObject( | 
|---|
| 165 | const void *creationContext, UErrorCode &status) const override; | 
|---|
| 166 | /** | 
|---|
| 167 | * Use the locale id as the description. | 
|---|
| 168 | */ | 
|---|
| 169 | virtual char *writeDescription(char *buffer, int32_t bufLen) const override { | 
|---|
| 170 | const char *s = fLoc.getName(); | 
|---|
| 171 | uprv_strncpy(buffer, s, bufLen); | 
|---|
| 172 | buffer[bufLen - 1] = 0; | 
|---|
| 173 | return buffer; | 
|---|
| 174 | } | 
|---|
| 175 |  | 
|---|
| 176 | }; | 
|---|
| 177 |  | 
|---|
| 178 | /** | 
|---|
| 179 | * The unified cache. A singleton type. | 
|---|
| 180 | * Design doc here: | 
|---|
| 181 | * https://docs.google.com/document/d/1RwGQJs4N4tawNbf809iYDRCvXoMKqDJihxzYt1ysmd8/edit?usp=sharing | 
|---|
| 182 | */ | 
|---|
| 183 | class U_COMMON_API UnifiedCache : public UnifiedCacheBase { | 
|---|
| 184 | public: | 
|---|
| 185 | /** | 
|---|
| 186 | * @internal | 
|---|
| 187 | * Do not call directly. Instead use UnifiedCache::getInstance() as | 
|---|
| 188 | * there should be only one UnifiedCache in an application. | 
|---|
| 189 | */ | 
|---|
| 190 | UnifiedCache(UErrorCode &status); | 
|---|
| 191 |  | 
|---|
| 192 | /** | 
|---|
| 193 | * Return a pointer to the global cache instance. | 
|---|
| 194 | */ | 
|---|
| 195 | static UnifiedCache *getInstance(UErrorCode &status); | 
|---|
| 196 |  | 
|---|
| 197 | /** | 
|---|
| 198 | * Fetches a value from the cache by key. Equivalent to | 
|---|
| 199 | * get(key, nullptr, ptr, status); | 
|---|
| 200 | */ | 
|---|
| 201 | template<typename T> | 
|---|
| 202 | void get( | 
|---|
| 203 | const CacheKey<T>& key, | 
|---|
| 204 | const T *&ptr, | 
|---|
| 205 | UErrorCode &status) const { | 
|---|
| 206 | get(key, nullptr, ptr, status); | 
|---|
| 207 | } | 
|---|
| 208 |  | 
|---|
| 209 | /** | 
|---|
| 210 | * Fetches value from the cache by key. | 
|---|
| 211 | * | 
|---|
| 212 | * @param key             the cache key. | 
|---|
| 213 | * @param creationContext passed verbatim to createObject method of key | 
|---|
| 214 | * @param ptr             On entry, ptr must be nullptr or be included if | 
|---|
| 215 | *                        the reference count of the object it points | 
|---|
| 216 | *                        to. On exit, ptr points to the fetched object | 
|---|
| 217 | *                        from the cache or is left unchanged on | 
|---|
| 218 | *                        failure. Caller must call removeRef on ptr | 
|---|
| 219 | *                        if set to a non nullptr value. | 
|---|
| 220 | * @param status          Any error returned here. May be set to a | 
|---|
| 221 | *                        warning value even if ptr is set. | 
|---|
| 222 | */ | 
|---|
| 223 | template<typename T> | 
|---|
| 224 | void get( | 
|---|
| 225 | const CacheKey<T>& key, | 
|---|
| 226 | const void *creationContext, | 
|---|
| 227 | const T *&ptr, | 
|---|
| 228 | UErrorCode &status) const { | 
|---|
| 229 | if (U_FAILURE(status)) { | 
|---|
| 230 | return; | 
|---|
| 231 | } | 
|---|
| 232 | UErrorCode creationStatus = U_ZERO_ERROR; | 
|---|
| 233 | const SharedObject *value = nullptr; | 
|---|
| 234 | _get(key, value, creationContext, creationStatus); | 
|---|
| 235 | const T *tvalue = (const T *) value; | 
|---|
| 236 | if (U_SUCCESS(creationStatus)) { | 
|---|
| 237 | SharedObject::copyPtr(tvalue, ptr); | 
|---|
| 238 | } | 
|---|
| 239 | SharedObject::clearPtr(tvalue); | 
|---|
| 240 | // Take care not to overwrite a warning status passed in with | 
|---|
| 241 | // another warning or U_ZERO_ERROR. | 
|---|
| 242 | if (status == U_ZERO_ERROR || U_FAILURE(creationStatus)) { | 
|---|
| 243 | status = creationStatus; | 
|---|
| 244 | } | 
|---|
| 245 | } | 
|---|
| 246 |  | 
|---|
| 247 | #ifdef UNIFIED_CACHE_DEBUG | 
|---|
| 248 | /** | 
|---|
| 249 | * Dumps the contents of this cache to standard error. Used for testing of | 
|---|
| 250 | * cache only. | 
|---|
| 251 | */ | 
|---|
| 252 | void dumpContents() const; | 
|---|
| 253 | #endif | 
|---|
| 254 |  | 
|---|
| 255 | /** | 
|---|
| 256 | * Convenience method to get a value of type T from cache for a | 
|---|
| 257 | * particular locale with creationContext == nullptr. | 
|---|
| 258 | * @param loc    the locale | 
|---|
| 259 | * @param ptr    On entry, must be nullptr or included in the ref count | 
|---|
| 260 | *               of the object to which it points. | 
|---|
| 261 | *               On exit, fetched value stored here or is left | 
|---|
| 262 | *               unchanged on failure. Caller must call removeRef on | 
|---|
| 263 | *               ptr if set to a non nullptr value. | 
|---|
| 264 | * @param status Any error returned here. May be set to a | 
|---|
| 265 | *               warning value even if ptr is set. | 
|---|
| 266 | */ | 
|---|
| 267 | template<typename T> | 
|---|
| 268 | static void getByLocale( | 
|---|
| 269 | const Locale &loc, const T *&ptr, UErrorCode &status) { | 
|---|
| 270 | const UnifiedCache *cache = getInstance(status); | 
|---|
| 271 | if (U_FAILURE(status)) { | 
|---|
| 272 | return; | 
|---|
| 273 | } | 
|---|
| 274 | cache->get(LocaleCacheKey<T>(loc), ptr, status); | 
|---|
| 275 | } | 
|---|
| 276 |  | 
|---|
| 277 | #ifdef UNIFIED_CACHE_DEBUG | 
|---|
| 278 | /** | 
|---|
| 279 | * Dumps the cache contents to stderr. For testing only. | 
|---|
| 280 | */ | 
|---|
| 281 | static void dump(); | 
|---|
| 282 | #endif | 
|---|
| 283 |  | 
|---|
| 284 | /** | 
|---|
| 285 | * Returns the number of keys in this cache. For testing only. | 
|---|
| 286 | */ | 
|---|
| 287 | int32_t keyCount() const; | 
|---|
| 288 |  | 
|---|
| 289 | /** | 
|---|
| 290 | * Removes any values from cache that are not referenced outside | 
|---|
| 291 | * the cache. | 
|---|
| 292 | */ | 
|---|
| 293 | void flush() const; | 
|---|
| 294 |  | 
|---|
| 295 | /** | 
|---|
| 296 | * Configures at what point eviction of unused entries will begin. | 
|---|
| 297 | * Eviction is triggered whenever the number of evictable keys exceeds | 
|---|
| 298 | * BOTH count AND (number of in-use items) * (percentageOfInUseItems / 100). | 
|---|
| 299 | * Once the number of unused entries drops below one of these, | 
|---|
| 300 | * eviction ceases. Because eviction happens incrementally, | 
|---|
| 301 | * the actual unused entry count may exceed both these numbers | 
|---|
| 302 | * from time to time. | 
|---|
| 303 | * | 
|---|
| 304 | * A cache entry is defined as unused if it is not essential to guarantee | 
|---|
| 305 | * that for a given key X, the cache returns the same reference to the | 
|---|
| 306 | * same value as long as the client already holds a reference to that | 
|---|
| 307 | * value. | 
|---|
| 308 | * | 
|---|
| 309 | * If this method is never called, the default settings are 1000 and 100%. | 
|---|
| 310 | * | 
|---|
| 311 | * Although this method is thread-safe, it is designed to be called at | 
|---|
| 312 | * application startup. If it is called in the middle of execution, it | 
|---|
| 313 | * will have no immediate effect on the cache. However over time, the | 
|---|
| 314 | * cache will perform eviction slices in an attempt to honor the new | 
|---|
| 315 | * settings. | 
|---|
| 316 | * | 
|---|
| 317 | * If a client already holds references to many different unique values | 
|---|
| 318 | * in the cache such that the number of those unique values far exceeds | 
|---|
| 319 | * "count" then the cache may not be able to maintain this maximum. | 
|---|
| 320 | * However, if this happens, the cache still guarantees that the number of | 
|---|
| 321 | * unused entries will remain only a small percentage of the total cache | 
|---|
| 322 | * size. | 
|---|
| 323 | * | 
|---|
| 324 | * If the parameters passed are negative, setEvctionPolicy sets status to | 
|---|
| 325 | * U_ILLEGAL_ARGUMENT_ERROR. | 
|---|
| 326 | */ | 
|---|
| 327 | void setEvictionPolicy( | 
|---|
| 328 | int32_t count, int32_t percentageOfInUseItems, UErrorCode &status); | 
|---|
| 329 |  | 
|---|
| 330 |  | 
|---|
| 331 | /** | 
|---|
| 332 | * Returns how many entries have been auto evicted during the lifetime | 
|---|
| 333 | * of this cache. This only includes auto evicted entries, not | 
|---|
| 334 | * entries evicted because of a call to flush(). | 
|---|
| 335 | */ | 
|---|
| 336 | int64_t autoEvictedCount() const; | 
|---|
| 337 |  | 
|---|
| 338 | /** | 
|---|
| 339 | * Returns the unused entry count in this cache. For testing only, | 
|---|
| 340 | * Regular clients will not need this. | 
|---|
| 341 | */ | 
|---|
| 342 | int32_t unusedCount() const; | 
|---|
| 343 |  | 
|---|
| 344 | virtual void handleUnreferencedObject() const override; | 
|---|
| 345 | virtual ~UnifiedCache(); | 
|---|
| 346 |  | 
|---|
| 347 | private: | 
|---|
| 348 | UHashtable *fHashtable; | 
|---|
| 349 | mutable int32_t fEvictPos; | 
|---|
| 350 | mutable int32_t fNumValuesTotal; | 
|---|
| 351 | mutable int32_t fNumValuesInUse; | 
|---|
| 352 | int32_t fMaxUnused; | 
|---|
| 353 | int32_t fMaxPercentageOfInUse; | 
|---|
| 354 | mutable int64_t fAutoEvictedCount; | 
|---|
| 355 | SharedObject *fNoValue; | 
|---|
| 356 |  | 
|---|
| 357 | UnifiedCache(const UnifiedCache &other) = delete; | 
|---|
| 358 | UnifiedCache &operator=(const UnifiedCache &other) = delete; | 
|---|
| 359 |  | 
|---|
| 360 | /** | 
|---|
| 361 | * Flushes the contents of the cache. If cache values hold references to other | 
|---|
| 362 | * cache values then _flush should be called in a loop until it returns false. | 
|---|
| 363 | * | 
|---|
| 364 | * On entry, gCacheMutex must be held. | 
|---|
| 365 | * On exit, those values with are evictable are flushed. | 
|---|
| 366 | * | 
|---|
| 367 | *  @param all if false flush evictable items only, which are those with no external | 
|---|
| 368 | *                    references, plus those that can be safely recreated.<br> | 
|---|
| 369 | *            if true, flush all elements. Any values (sharedObjects) with remaining | 
|---|
| 370 | *                     hard (external) references are not deleted, but are detached from | 
|---|
| 371 | *                     the cache, so that a subsequent removeRefs can delete them. | 
|---|
| 372 | *                     _flush is not thread safe when all is true. | 
|---|
| 373 | *   @return true if any value in cache was flushed or false otherwise. | 
|---|
| 374 | */ | 
|---|
| 375 | UBool _flush(UBool all) const; | 
|---|
| 376 |  | 
|---|
| 377 | /** | 
|---|
| 378 | * Gets value out of cache. | 
|---|
| 379 | * On entry. gCacheMutex must not be held. value must be nullptr. status | 
|---|
| 380 | * must be U_ZERO_ERROR. | 
|---|
| 381 | * On exit. value and status set to what is in cache at key or on cache | 
|---|
| 382 | * miss the key's createObject() is called and value and status are set to | 
|---|
| 383 | * the result of that. In this latter case, best effort is made to add the | 
|---|
| 384 | * value and status to the cache. If createObject() fails to create a value, | 
|---|
| 385 | * fNoValue is stored in cache, and value is set to nullptr. Caller must call | 
|---|
| 386 | * removeRef on value if non nullptr. | 
|---|
| 387 | */ | 
|---|
| 388 | void _get( | 
|---|
| 389 | const CacheKeyBase &key, | 
|---|
| 390 | const SharedObject *&value, | 
|---|
| 391 | const void *creationContext, | 
|---|
| 392 | UErrorCode &status) const; | 
|---|
| 393 |  | 
|---|
| 394 | /** | 
|---|
| 395 | * Attempts to fetch value and status for key from cache. | 
|---|
| 396 | * On entry, gCacheMutex must not be held value must be nullptr and status must | 
|---|
| 397 | * be U_ZERO_ERROR. | 
|---|
| 398 | * On exit, either returns false (In this | 
|---|
| 399 | * case caller should try to create the object) or returns true with value | 
|---|
| 400 | * pointing to the fetched value and status set to fetched status. When | 
|---|
| 401 | * false is returned status may be set to failure if an in progress hash | 
|---|
| 402 | * entry could not be made but value will remain unchanged. When true is | 
|---|
| 403 | * returned, caller must call removeRef() on value. | 
|---|
| 404 | */ | 
|---|
| 405 | UBool _poll( | 
|---|
| 406 | const CacheKeyBase &key, | 
|---|
| 407 | const SharedObject *&value, | 
|---|
| 408 | UErrorCode &status) const; | 
|---|
| 409 |  | 
|---|
| 410 | /** | 
|---|
| 411 | * Places a new value and creationStatus in the cache for the given key. | 
|---|
| 412 | * On entry, gCacheMutex must be held. key must not exist in the cache. | 
|---|
| 413 | * On exit, value and creation status placed under key. Soft reference added | 
|---|
| 414 | * to value on successful add. On error sets status. | 
|---|
| 415 | */ | 
|---|
| 416 | void _putNew( | 
|---|
| 417 | const CacheKeyBase &key, | 
|---|
| 418 | const SharedObject *value, | 
|---|
| 419 | const UErrorCode creationStatus, | 
|---|
| 420 | UErrorCode &status) const; | 
|---|
| 421 |  | 
|---|
| 422 | /** | 
|---|
| 423 | * Places value and status at key if there is no value at key or if cache | 
|---|
| 424 | * entry for key is in progress. Otherwise, it leaves the current value and | 
|---|
| 425 | * status there. | 
|---|
| 426 | * | 
|---|
| 427 | * On entry. gCacheMutex must not be held. Value must be | 
|---|
| 428 | * included in the reference count of the object to which it points. | 
|---|
| 429 | * | 
|---|
| 430 | * On exit, value and status are changed to what was already in the cache if | 
|---|
| 431 | * something was there and not in progress. Otherwise, value and status are left | 
|---|
| 432 | * unchanged in which case they are placed in the cache on a best-effort basis. | 
|---|
| 433 | * Caller must call removeRef() on value. | 
|---|
| 434 | */ | 
|---|
| 435 | void _putIfAbsentAndGet( | 
|---|
| 436 | const CacheKeyBase &key, | 
|---|
| 437 | const SharedObject *&value, | 
|---|
| 438 | UErrorCode &status) const; | 
|---|
| 439 |  | 
|---|
| 440 | /** | 
|---|
| 441 | * Returns the next element in the cache round robin style. | 
|---|
| 442 | * Returns nullptr if the cache is empty. | 
|---|
| 443 | * On entry, gCacheMutex must be held. | 
|---|
| 444 | */ | 
|---|
| 445 | const UHashElement *_nextElement() const; | 
|---|
| 446 |  | 
|---|
| 447 | /** | 
|---|
| 448 | * Return the number of cache items that would need to be evicted | 
|---|
| 449 | * to bring usage into conformance with eviction policy. | 
|---|
| 450 | * | 
|---|
| 451 | * An item corresponds to an entry in the hash table, a hash table element. | 
|---|
| 452 | * | 
|---|
| 453 | * On entry, gCacheMutex must be held. | 
|---|
| 454 | */ | 
|---|
| 455 | int32_t _computeCountOfItemsToEvict() const; | 
|---|
| 456 |  | 
|---|
| 457 | /** | 
|---|
| 458 | * Run an eviction slice. | 
|---|
| 459 | * On entry, gCacheMutex must be held. | 
|---|
| 460 | * _runEvictionSlice runs a slice of the evict pipeline by examining the next | 
|---|
| 461 | * 10 entries in the cache round robin style evicting them if they are eligible. | 
|---|
| 462 | */ | 
|---|
| 463 | void _runEvictionSlice() const; | 
|---|
| 464 |  | 
|---|
| 465 | /** | 
|---|
| 466 | * Register a primary cache entry. A primary key is the first key to create | 
|---|
| 467 | * a given  SharedObject value. Subsequent keys whose create function | 
|---|
| 468 | * produce references to an already existing SharedObject are not primary - | 
|---|
| 469 | * they can be evicted and subsequently recreated. | 
|---|
| 470 | * | 
|---|
| 471 | * On entry, gCacheMutex must be held. | 
|---|
| 472 | * On exit, items in use count incremented, entry is marked as a primary | 
|---|
| 473 | * entry, and value registered with cache so that subsequent calls to | 
|---|
| 474 | * addRef() and removeRef() on it correctly interact with the cache. | 
|---|
| 475 | */ | 
|---|
| 476 | void _registerPrimary(const CacheKeyBase *theKey, const SharedObject *value) const; | 
|---|
| 477 |  | 
|---|
| 478 | /** | 
|---|
| 479 | * Store a value and creation error status in given hash entry. | 
|---|
| 480 | * On entry, gCacheMutex must be held. Hash entry element must be in progress. | 
|---|
| 481 | * value must be non nullptr. | 
|---|
| 482 | * On Exit, soft reference added to value. value and status stored in hash | 
|---|
| 483 | * entry. Soft reference removed from previous stored value. Waiting | 
|---|
| 484 | * threads notified. | 
|---|
| 485 | */ | 
|---|
| 486 | void _put( | 
|---|
| 487 | const UHashElement *element, | 
|---|
| 488 | const SharedObject *value, | 
|---|
| 489 | const UErrorCode status) const; | 
|---|
| 490 | /** | 
|---|
| 491 | * Remove a soft reference, and delete the SharedObject if no references remain. | 
|---|
| 492 | * To be used from within the UnifiedCache implementation only. | 
|---|
| 493 | * gCacheMutex must be held by caller. | 
|---|
| 494 | * @param value the SharedObject to be acted on. | 
|---|
| 495 | */ | 
|---|
| 496 | void removeSoftRef(const SharedObject *value) const; | 
|---|
| 497 |  | 
|---|
| 498 | /** | 
|---|
| 499 | * Increment the hard reference count of the given SharedObject. | 
|---|
| 500 | * gCacheMutex must be held by the caller. | 
|---|
| 501 | * Update numValuesEvictable on transitions between zero and one reference. | 
|---|
| 502 | * | 
|---|
| 503 | * @param value The SharedObject to be referenced. | 
|---|
| 504 | * @return the hard reference count after the addition. | 
|---|
| 505 | */ | 
|---|
| 506 | int32_t addHardRef(const SharedObject *value) const; | 
|---|
| 507 |  | 
|---|
| 508 | /** | 
|---|
| 509 | * Decrement the hard reference count of the given SharedObject. | 
|---|
| 510 | * gCacheMutex must be held by the caller. | 
|---|
| 511 | * Update numValuesEvictable on transitions between one and zero reference. | 
|---|
| 512 | * | 
|---|
| 513 | * @param value The SharedObject to be referenced. | 
|---|
| 514 | * @return the hard reference count after the removal. | 
|---|
| 515 | */ | 
|---|
| 516 | int32_t removeHardRef(const SharedObject *value) const; | 
|---|
| 517 |  | 
|---|
| 518 |  | 
|---|
| 519 | #ifdef UNIFIED_CACHE_DEBUG | 
|---|
| 520 | void _dumpContents() const; | 
|---|
| 521 | #endif | 
|---|
| 522 |  | 
|---|
| 523 | /** | 
|---|
| 524 | *  Fetch value and error code from a particular hash entry. | 
|---|
| 525 | *  On entry, gCacheMutex must be held. value must be either nullptr or must be | 
|---|
| 526 | *  included in the ref count of the object to which it points. | 
|---|
| 527 | *  On exit, value and status set to what is in the hash entry. Caller must | 
|---|
| 528 | *  eventually call removeRef on value. | 
|---|
| 529 | *  If hash entry is in progress, value will be set to gNoValue and status will | 
|---|
| 530 | *  be set to U_ZERO_ERROR. | 
|---|
| 531 | */ | 
|---|
| 532 | void _fetch(const UHashElement *element, const SharedObject *&value, | 
|---|
| 533 | UErrorCode &status) const; | 
|---|
| 534 |  | 
|---|
| 535 | /** | 
|---|
| 536 | * Determine if given hash entry is in progress. | 
|---|
| 537 | * On entry, gCacheMutex must be held. | 
|---|
| 538 | */ | 
|---|
| 539 | UBool _inProgress(const UHashElement *element) const; | 
|---|
| 540 |  | 
|---|
| 541 | /** | 
|---|
| 542 | * Determine if given hash entry is in progress. | 
|---|
| 543 | * On entry, gCacheMutex must be held. | 
|---|
| 544 | */ | 
|---|
| 545 | UBool _inProgress(const SharedObject *theValue, UErrorCode creationStatus) const; | 
|---|
| 546 |  | 
|---|
| 547 | /** | 
|---|
| 548 | * Determine if given hash entry is eligible for eviction. | 
|---|
| 549 | * On entry, gCacheMutex must be held. | 
|---|
| 550 | */ | 
|---|
| 551 | UBool _isEvictable(const UHashElement *element) const; | 
|---|
| 552 | }; | 
|---|
| 553 |  | 
|---|
| 554 | U_NAMESPACE_END | 
|---|
| 555 |  | 
|---|
| 556 | #endif | 
|---|
| 557 |  | 
|---|