2 ******************************************************************************
3 * Copyright (C) 2014, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ******************************************************************************
7 * File UNIFIEDCACHE.H - The ICU Unified cache.
8 ******************************************************************************
11 #ifndef __UNIFIED_CACHE_H__
12 #define __UNIFIED_CACHE_H__
14 #include "utypeinfo.h" // for 'typeid' to work
16 #include "unicode/uobject.h"
17 #include "unicode/locid.h"
18 #include "sharedobject.h"
19 #include "unicode/unistr.h"
31 * A base class for all cache keys
33 class U_COMMON_API CacheKeyBase
: public UObject
{
35 CacheKeyBase() : creationStatus(U_ZERO_ERROR
) {}
38 * Copy constructor. Needed to support cloning.
40 CacheKeyBase(const CacheKeyBase
&other
)
41 : UObject(other
), creationStatus(other
.creationStatus
) { }
42 virtual ~CacheKeyBase();
45 * Returns the hash code for this object.
47 virtual int32_t hashCode() const = 0;
50 * Clones this object polymorphically. Caller owns returned value.
52 virtual CacheKeyBase
*clone() const = 0;
57 virtual UBool
operator == (const CacheKeyBase
&other
) const = 0;
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.
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.
72 virtual const SharedObject
*createObject(
73 const void *creationContext
, UErrorCode
&status
) const = 0;
76 * Writes a description of this key to buffer and returns buffer. Written
77 * description is NULL terminated.
79 virtual char *writeDescription(char *buffer
, int32_t bufSize
) const = 0;
82 * Inequality operator.
84 UBool
operator != (const CacheKeyBase
&other
) const {
85 return !(*this == other
);
88 mutable UErrorCode creationStatus
;
89 friend class UnifiedCache
;
95 * Templated version of CacheKeyBase.
96 * A key of type LocaleCacheKey<T> maps to a value of type T.
99 class CacheKey
: public CacheKeyBase
{
101 virtual ~CacheKey() { }
103 * The template parameter, T, determines the hash code returned.
105 virtual int32_t hashCode() const {
106 const char *s
= typeid(T
).name();
107 return ustr_hashCharsN(s
, uprv_strlen(s
));
111 * Use the value type, T, as the description.
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;
121 * Two objects are equal if they are of the same type.
123 virtual UBool
operator == (const CacheKeyBase
&other
) const {
124 return typeid(*this) == typeid(other
);
129 * Cache key based on locale.
130 * A key of type LocaleCacheKey<T> maps to a value of type T.
133 class LocaleCacheKey
: public CacheKey
<T
> {
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();
144 virtual UBool
operator == (const CacheKeyBase
&other
) const {
146 if (this == &other
) {
149 if (!CacheKey
<T
>::operator == (other
)) {
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
;
158 virtual CacheKeyBase
*clone() const {
159 return new LocaleCacheKey
<T
>(*this);
161 virtual const T
*createObject(
162 const void *creationContext
, UErrorCode
&status
) const;
164 * Use the locale id as the description.
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;
176 * The unified cache. A singleton type.
178 class U_COMMON_API UnifiedCache
: public UObject
{
183 UnifiedCache(UErrorCode
&status
);
186 * Returns the cache instance.
188 static const UnifiedCache
*getInstance(UErrorCode
&status
);
191 * Fetches a value from the cache by key. Equivalent to
192 * get(key, NULL, ptr, status);
196 const CacheKey
<T
>& key
,
198 UErrorCode
&status
) const {
199 get(key
, NULL
, ptr
, status
);
203 * Fetches value from the cache by key.
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.
218 const CacheKey
<T
>& key
,
219 const void *creationContext
,
221 UErrorCode
&status
) const {
222 if (U_FAILURE(status
)) {
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
);
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
;
240 #ifdef UNIFIED_CACHE_DEBUG
242 * Dumps the contents of this cache to standard error. Used for testing of
245 void dumpContents() const;
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.
261 static void getByLocale(
262 const Locale
&loc
, const T
*&ptr
, UErrorCode
&status
) {
263 const UnifiedCache
*cache
= getInstance(status
);
264 if (U_FAILURE(status
)) {
267 cache
->get(LocaleCacheKey
<T
>(loc
), ptr
, status
);
270 #ifdef UNIFIED_CACHE_DEBUG
272 * Dumps the cache contents to stderr. For testing only.
278 * Returns the number of keys in this cache. For testing only.
280 int32_t keyCount() const;
283 * Removes any values from cache that are not referenced outside
288 virtual ~UnifiedCache();
290 UHashtable
*fHashtable
;
291 UnifiedCache(const UnifiedCache
&other
);
292 UnifiedCache
&operator=(const UnifiedCache
&other
);
293 UBool
_flush(UBool all
) const;
295 const CacheKeyBase
&key
,
296 const SharedObject
*&value
,
297 const void *creationContext
,
298 UErrorCode
&status
) const;
300 const CacheKeyBase
&key
,
301 const SharedObject
*&value
,
302 UErrorCode
&status
) const;
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;
316 const UHashElement
*element
,
317 const SharedObject
*value
,
318 const UErrorCode status
);
320 const UHashElement
*element
,
321 const SharedObject
*&value
,
323 static UBool
_inProgress(const UHashElement
*element
);