LCOV - code coverage report
Current view: top level - intl/icu/source/common - unifiedcache.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 55 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 125 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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           0 :    CacheKeyBase() : fCreationStatus(U_ZERO_ERROR), fIsMaster(FALSE) {}
      38             : 
      39             :    /**
      40             :     * Copy constructor. Needed to support cloning.
      41             :     */
      42           0 :    CacheKeyBase(const CacheKeyBase &other) 
      43           0 :            : UObject(other), fCreationStatus(other.fCreationStatus), fIsMaster(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             :     * Equality operator.
      58             :     */
      59             :    virtual UBool operator == (const CacheKeyBase &other) const = 0;
      60             : 
      61             :    /**
      62             :     * Create a new object for this key. Called by cache on cache miss.
      63             :     * createObject must add a reference to the object it returns. Note
      64             :     * that getting an object from the cache and returning it without calling
      65             :     * removeRef on it satisfies this requirement. It can also return NULL
      66             :     * and set status to an error.
      67             :     *
      68             :     * @param creationContext the context in which the object is being
      69             :     *                        created. May be NULL.
      70             :     * @param status          Implementations can return a failure here.
      71             :     *                        In addition, implementations may return a
      72             :     *                        non NULL object and set a warning status.
      73             :     */
      74             :    virtual const SharedObject *createObject(
      75             :            const void *creationContext, UErrorCode &status) const = 0;
      76             : 
      77             :    /**
      78             :     * Writes a description of this key to buffer and returns buffer. Written
      79             :     * description is NULL terminated.
      80             :     */
      81             :    virtual char *writeDescription(char *buffer, int32_t bufSize) const = 0;
      82             : 
      83             :    /**
      84             :     * Inequality operator.
      85             :     */
      86             :    UBool operator != (const CacheKeyBase &other) const {
      87             :        return !(*this == other);
      88             :    }
      89             :  private:
      90             :    mutable UErrorCode fCreationStatus;
      91             :    mutable UBool fIsMaster;
      92             :    friend class UnifiedCache;
      93             : };
      94             : 
      95             : 
      96             : 
      97             : /**
      98             :  * Templated version of CacheKeyBase. 
      99             :  * A key of type LocaleCacheKey<T> maps to a value of type T.
     100             :  */
     101             : template<typename T>
     102           0 : class CacheKey : public CacheKeyBase {
     103             :  public:
     104           0 :    virtual ~CacheKey() { }
     105             :    /**
     106             :     * The template parameter, T, determines the hash code returned.
     107             :     */
     108           0 :    virtual int32_t hashCode() const {
     109           0 :        const char *s = typeid(T).name();
     110           0 :        return ustr_hashCharsN(s, uprv_strlen(s));
     111             :    }
     112             : 
     113             :    /**
     114             :     * Use the value type, T,  as the description.
     115             :     */
     116           0 :    virtual char *writeDescription(char *buffer, int32_t bufLen) const {
     117           0 :        const char *s = typeid(T).name();
     118           0 :        uprv_strncpy(buffer, s, bufLen);
     119           0 :        buffer[bufLen - 1] = 0;
     120           0 :        return buffer;
     121             :    }
     122             : 
     123             :    /**
     124             :     * Two objects are equal if they are of the same type.
     125             :     */
     126           0 :    virtual UBool operator == (const CacheKeyBase &other) const {
     127           0 :        return typeid(*this) == typeid(other);
     128             :    }
     129             : };
     130             : 
     131             : /**
     132             :  * Cache key based on locale.
     133             :  * A key of type LocaleCacheKey<T> maps to a value of type T.
     134             :  */
     135             : template<typename T>
     136             : class LocaleCacheKey : public CacheKey<T> {
     137             :  protected:
     138             :    Locale   fLoc;
     139             :  public:
     140           0 :    LocaleCacheKey(const Locale &loc) : fLoc(loc) {};
     141           0 :    LocaleCacheKey(const LocaleCacheKey<T> &other)
     142           0 :            : CacheKey<T>(other), fLoc(other.fLoc) { }
     143           0 :    virtual ~LocaleCacheKey() { }
     144           0 :    virtual int32_t hashCode() const {
     145           0 :        return (int32_t)(37u * (uint32_t)CacheKey<T>::hashCode() + (uint32_t)fLoc.hashCode());
     146             :    }
     147           0 :    virtual UBool operator == (const CacheKeyBase &other) const {
     148             :        // reflexive
     149           0 :        if (this == &other) {
     150           0 :            return TRUE;
     151             :        }
     152           0 :        if (!CacheKey<T>::operator == (other)) {
     153           0 :            return FALSE;
     154             :        }
     155             :        // We know this and other are of same class because operator== on
     156             :        // CacheKey returned true.
     157             :        const LocaleCacheKey<T> *fOther =
     158           0 :                static_cast<const LocaleCacheKey<T> *>(&other);
     159           0 :        return fLoc == fOther->fLoc;
     160             :    }
     161           0 :    virtual CacheKeyBase *clone() const {
     162           0 :        return new LocaleCacheKey<T>(*this);
     163             :    }
     164             :    virtual const T *createObject(
     165             :            const void *creationContext, UErrorCode &status) const;
     166             :    /**
     167             :     * Use the locale id as the description.
     168             :     */
     169           0 :    virtual char *writeDescription(char *buffer, int32_t bufLen) const {
     170           0 :        const char *s = fLoc.getName();
     171           0 :        uprv_strncpy(buffer, s, bufLen);
     172           0 :        buffer[bufLen - 1] = 0;
     173           0 :        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             :     * Returns the 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, NULL, ptr, status);
     200             :     */
     201             :    template<typename T>
     202           0 :    void get(
     203             :            const CacheKey<T>& key,
     204             :            const T *&ptr,
     205             :            UErrorCode &status) const {
     206           0 :        get(key, NULL, ptr, status);
     207           0 :    }
     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 NULL 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 NULL 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           0 :    void get(
     225             :            const CacheKey<T>& key,
     226             :            const void *creationContext,
     227             :            const T *&ptr,
     228             :            UErrorCode &status) const {
     229           0 :        if (U_FAILURE(status)) {
     230           0 :            return;
     231             :        }
     232           0 :        UErrorCode creationStatus = U_ZERO_ERROR;
     233           0 :        const SharedObject *value = NULL;
     234           0 :        _get(key, value, creationContext, creationStatus);
     235           0 :        const T *tvalue = (const T *) value;
     236           0 :        if (U_SUCCESS(creationStatus)) {
     237           0 :            SharedObject::copyPtr(tvalue, ptr);
     238             :        }
     239           0 :        SharedObject::clearPtr(tvalue);
     240             :        // Take care not to overwrite a warning status passed in with
     241             :        // another warning or U_ZERO_ERROR.
     242           0 :        if (status == U_ZERO_ERROR || U_FAILURE(creationStatus)) {
     243           0 :            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 == NULL.
     258             :     * @param loc    the locale
     259             :     * @param ptr    On entry, must be NULL 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 NULL 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           0 :    static void getByLocale(
     269             :            const Locale &loc, const T *&ptr, UErrorCode &status) {
     270           0 :        const UnifiedCache *cache = getInstance(status);
     271           0 :        if (U_FAILURE(status)) {
     272           0 :            return;
     273             :        }
     274           0 :        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 evcition of unused entries will begin.
     297             :     * Eviction is triggered whenever the number of unused entries exeeds
     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 exeeds
     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 incrementItemsInUse() const;
     345             :    virtual void decrementItemsInUseWithLockingAndEviction() const;
     346             :    virtual void decrementItemsInUse() const;
     347             :    virtual ~UnifiedCache();
     348             :  private:
     349             :    UHashtable *fHashtable;
     350             :    mutable int32_t fEvictPos;
     351             :    mutable int32_t fItemsInUseCount;
     352             :    int32_t fMaxUnused;
     353             :    int32_t fMaxPercentageOfInUse;
     354             :    mutable int64_t fAutoEvictedCount;
     355             :    UnifiedCache(const UnifiedCache &other);
     356             :    UnifiedCache &operator=(const UnifiedCache &other);
     357             :    UBool _flush(UBool all) const;
     358             :    void _get(
     359             :            const CacheKeyBase &key,
     360             :            const SharedObject *&value,
     361             :            const void *creationContext,
     362             :            UErrorCode &status) const;
     363             :    UBool _poll(
     364             :            const CacheKeyBase &key,
     365             :            const SharedObject *&value,
     366             :            UErrorCode &status) const;
     367             :    void _putNew(
     368             :            const CacheKeyBase &key,
     369             :            const SharedObject *value,
     370             :            const UErrorCode creationStatus,
     371             :            UErrorCode &status) const;
     372             :    void _putIfAbsentAndGet(
     373             :            const CacheKeyBase &key,
     374             :            const SharedObject *&value,
     375             :            UErrorCode &status) const;
     376             :    const UHashElement *_nextElement() const;
     377             :    int32_t _computeCountOfItemsToEvict() const;
     378             :    void _runEvictionSlice() const;
     379             :    void _registerMaster( 
     380             :         const CacheKeyBase *theKey, const SharedObject *value) const;
     381             :    void _put(
     382             :            const UHashElement *element,
     383             :            const SharedObject *value,
     384             :            const UErrorCode status) const;
     385             : #ifdef UNIFIED_CACHE_DEBUG
     386             :    void _dumpContents() const;
     387             : #endif
     388             :    static void copyPtr(const SharedObject *src, const SharedObject *&dest);
     389             :    static void clearPtr(const SharedObject *&ptr);
     390             :    static void _fetch(
     391             :            const UHashElement *element,
     392             :            const SharedObject *&value,
     393             :            UErrorCode &status);
     394             :    static UBool _inProgress(const UHashElement *element);
     395             :    static UBool _inProgress(
     396             :            const SharedObject *theValue, UErrorCode creationStatus);
     397             :    static UBool _isEvictable(const UHashElement *element);
     398             : };
     399             : 
     400             : U_NAMESPACE_END
     401             : 
     402             : #endif

Generated by: LCOV version 1.13