X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/b331163bffd790ced0e88b73f44f86d49ccc48a5..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/common/sharedobject.h diff --git a/icuSources/common/sharedobject.h b/icuSources/common/sharedobject.h index 432c79ba..d0b93039 100644 --- a/icuSources/common/sharedobject.h +++ b/icuSources/common/sharedobject.h @@ -1,6 +1,6 @@ /* ****************************************************************************** -* Copyright (C) 2014, International Business Machines +* Copyright (C) 2015-2016, International Business Machines * Corporation and others. All Rights Reserved. ****************************************************************************** * sharedobject.h @@ -15,6 +15,39 @@ U_NAMESPACE_BEGIN +/** + * Base class for unified cache exposing enough methods to SharedObject + * instances to allow their addRef() and removeRef() methods to + * update cache metrics. No other part of ICU, except for SharedObject, + * should directly call the methods of this base class. + */ +class U_COMMON_API UnifiedCacheBase : public UObject { +public: + UnifiedCacheBase() { } + + /** + * Called by addRefWhileHoldingCacheLock() when the hard reference count + * of its instance goes from 0 to 1. + */ + virtual void incrementItemsInUse() const = 0; + + /** + * Called by removeRef() when the hard reference count of its instance + * drops from 1 to 0. + */ + virtual void decrementItemsInUseWithLockingAndEviction() const = 0; + + /** + * Called by removeRefWhileHoldingCacheLock() when the hard reference + * count of its instance drops from 1 to 0. + */ + virtual void decrementItemsInUse() const = 0; + virtual ~UnifiedCacheBase(); +private: + UnifiedCacheBase(const UnifiedCacheBase &); + UnifiedCacheBase &operator=(const UnifiedCacheBase &); +}; + /** * Base class for shared, reference-counted, auto-deleted objects. * Subclasses can be immutable. @@ -27,33 +60,57 @@ U_NAMESPACE_BEGIN class U_COMMON_API SharedObject : public UObject { public: /** Initializes totalRefCount, softRefCount to 0. */ - SharedObject() : totalRefCount(0), softRefCount(0) {} + SharedObject() : + totalRefCount(0), + softRefCount(0), + hardRefCount(0), + cachePtr(NULL) {} /** Initializes totalRefCount, softRefCount to 0. */ - SharedObject(const SharedObject &other) - : UObject(other), - totalRefCount(0), - softRefCount(0) {} + SharedObject(const SharedObject &other) : + UObject(other), + totalRefCount(0), + softRefCount(0), + hardRefCount(0), + cachePtr(NULL) {} virtual ~SharedObject(); /** * Increments the number of references to this object. Thread-safe. */ - void addRef() const; + void addRef() const { addRef(FALSE); } + + /** + * Increments the number of references to this object. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. + */ + void addRefWhileHoldingCacheLock() const { addRef(TRUE); } /** - * Increments the number of soft references to this object. Thread-safe. + * Increments the number of soft references to this object. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. */ void addSoftRef() const; /** * Decrements the number of references to this object. Thread-safe. */ - void removeRef() const; + void removeRef() const { removeRef(FALSE); } /** - * Decrements the number of soft references to this object. Thread-safe. + * Decrements the number of references to this object. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. + */ + void removeRefWhileHoldingCacheLock() const { removeRef(TRUE); } + + /** + * Decrements the number of soft references to this object. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. */ void removeSoftRef() const; @@ -64,22 +121,50 @@ public: int32_t getRefCount() const; /** - * Returns the count of soft references only. Uses a memory barrier. + * Returns the count of soft references only. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. + */ + int32_t getSoftRefCount() const { return softRefCount; } + + /** + * Returns the count of hard references only. Uses a memory barrier. * Used for testing the cache. Regular clients won't need this. */ - int32_t getSoftRefCount() const; + int32_t getHardRefCount() const; + + /** + * If noHardReferences() == TRUE then this object has no hard references. + * Must be called only from within the internals of UnifiedCache. + */ + inline UBool noHardReferences() const { return getHardRefCount() == 0; } /** - * If allSoftReferences() == TRUE then this object has only soft - * references. The converse is not necessarily true. + * If hasHardReferences() == TRUE then this object has hard references. + * Must be called only from within the internals of UnifiedCache. */ - UBool allSoftReferences() const; + inline UBool hasHardReferences() const { return getHardRefCount() != 0; } + + /** + * If noSoftReferences() == TRUE then this object has no soft references. + * Must be called only from within the internals of UnifiedCache and + * only while the cache global mutex is held. + */ + UBool noSoftReferences() const { return (softRefCount == 0); } /** * Deletes this object if it has no references or soft references. */ void deleteIfZeroRefCount() const; + /** + * @internal For UnifedCache use only to register this object with itself. + * Must be called before this object is exposed to multiple threads. + */ + void registerWithCache(const UnifiedCacheBase *ptr) const { + cachePtr = ptr; + } + /** * Returns a writable version of ptr. * If there is exactly one owner, then ptr itself is returned as a @@ -133,7 +218,15 @@ public: private: mutable u_atomic_int32_t totalRefCount; - mutable u_atomic_int32_t softRefCount; + + // Any thread modifying softRefCount must hold the global cache mutex + mutable int32_t softRefCount; + + mutable u_atomic_int32_t hardRefCount; + mutable const UnifiedCacheBase *cachePtr; + void addRef(UBool withCacheLock) const; + void removeRef(UBool withCacheLock) const; + }; U_NAMESPACE_END