]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/sharedobject.h
ICU-59131.0.1.tar.gz
[apple/icu.git] / icuSources / common / sharedobject.h
index 671bab137f69df49f967100825c607444b2e7b2d..d13265182d4e05dd9ca1f49928345e1efb8fbb4c 100644 (file)
@@ -1,6 +1,8 @@
+// © 2016 and later: Unicode, Inc. and others.
+// License & terms of use: http://www.unicode.org/copyright.html
 /*
 ******************************************************************************
-* Copyright (C) 2014, International Business Machines
+* Copyright (C) 2015-2016, International Business Machines
 * Corporation and others.  All Rights Reserved.
 ******************************************************************************
 * sharedobject.h
 
 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.
@@ -26,31 +61,112 @@ U_NAMESPACE_BEGIN
  */
 class U_COMMON_API SharedObject : public UObject {
 public:
-    /** Initializes refCount to 0. */
-    SharedObject() : refCount(0) {}
+    /** Initializes totalRefCount, softRefCount to 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),
+            hardRefCount(0),
+            cachePtr(NULL) {}
 
-    /** Initializes refCount to 0. */
-    SharedObject(const SharedObject &/*other*/) : refCount(0) {}
     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.
+     * 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 { removeRef(FALSE); }
 
     /**
-     * Decrements the number of references to this object,
-     * and auto-deletes "this" if the number becomes 0. 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 removeRef() const;
+    void removeRefWhileHoldingCacheLock() const { removeRef(TRUE); }
 
     /**
-     * Returns the reference counter. Uses a memory barrier.
+     * 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;
+
+    /**
+     * Returns the reference counter including soft references.
+     * Uses a memory barrier.
      */
     int32_t getRefCount() const;
 
+    /**
+     * 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 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 hasHardReferences() == TRUE then this object has hard references.
+     * Must be called only from within the internals of UnifiedCache.
+     */
+    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
@@ -78,7 +194,7 @@ public:
      * Makes dest an owner of the object pointed to by src while adjusting
      * reference counts and deleting the previous object dest pointed to
      * if necessary. Before this call is made, dest must either be NULL or
-     * own its object
+     * be included in the reference count of the object it points to
      *
      * T must be a subclass of SharedObject.
      */
@@ -92,7 +208,7 @@ public:
     }
 
     /**
-     * Equivalent to copy(NULL, dest).
+     * Equivalent to copyPtr(NULL, dest).
      */
     template<typename T>
     static void clearPtr(const T *&ptr) {
@@ -103,7 +219,16 @@ public:
     }
 
 private:
-    mutable u_atomic_int32_t refCount;
+    mutable u_atomic_int32_t totalRefCount;
+
+    // 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