2 ******************************************************************************
3 * Copyright (C) 2015-2016, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 ******************************************************************************
9 #ifndef __SHAREDOBJECT_H__
10 #define __SHAREDOBJECT_H__
13 #include "unicode/uobject.h"
19 * Base class for unified cache exposing enough methods to SharedObject
20 * instances to allow their addRef() and removeRef() methods to
21 * update cache metrics. No other part of ICU, except for SharedObject,
22 * should directly call the methods of this base class.
24 class U_COMMON_API UnifiedCacheBase
: public UObject
{
26 UnifiedCacheBase() { }
29 * Called by addRefWhileHoldingCacheLock() when the hard reference count
30 * of its instance goes from 0 to 1.
32 virtual void incrementItemsInUse() const = 0;
35 * Called by removeRef() when the hard reference count of its instance
38 virtual void decrementItemsInUseWithLockingAndEviction() const = 0;
41 * Called by removeRefWhileHoldingCacheLock() when the hard reference
42 * count of its instance drops from 1 to 0.
44 virtual void decrementItemsInUse() const = 0;
45 virtual ~UnifiedCacheBase();
47 UnifiedCacheBase(const UnifiedCacheBase
&);
48 UnifiedCacheBase
&operator=(const UnifiedCacheBase
&);
52 * Base class for shared, reference-counted, auto-deleted objects.
53 * Subclasses can be immutable.
54 * If they are mutable, then they must implement their copy constructor
55 * so that copyOnWrite() works.
57 * Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
58 * Sharing requires reference-counting.
60 class U_COMMON_API SharedObject
: public UObject
{
62 /** Initializes totalRefCount, softRefCount to 0. */
69 /** Initializes totalRefCount, softRefCount to 0. */
70 SharedObject(const SharedObject
&other
) :
77 virtual ~SharedObject();
80 * Increments the number of references to this object. Thread-safe.
82 void addRef() const { addRef(FALSE
); }
85 * Increments the number of references to this object.
86 * Must be called only from within the internals of UnifiedCache and
87 * only while the cache global mutex is held.
89 void addRefWhileHoldingCacheLock() const { addRef(TRUE
); }
92 * Increments the number of soft references to this object.
93 * Must be called only from within the internals of UnifiedCache and
94 * only while the cache global mutex is held.
96 void addSoftRef() const;
99 * Decrements the number of references to this object. Thread-safe.
101 void removeRef() const { removeRef(FALSE
); }
104 * Decrements the number of references to this object.
105 * Must be called only from within the internals of UnifiedCache and
106 * only while the cache global mutex is held.
108 void removeRefWhileHoldingCacheLock() const { removeRef(TRUE
); }
111 * Decrements the number of soft references to this object.
112 * Must be called only from within the internals of UnifiedCache and
113 * only while the cache global mutex is held.
115 void removeSoftRef() const;
118 * Returns the reference counter including soft references.
119 * Uses a memory barrier.
121 int32_t getRefCount() const;
124 * Returns the count of soft references only.
125 * Must be called only from within the internals of UnifiedCache and
126 * only while the cache global mutex is held.
128 int32_t getSoftRefCount() const { return softRefCount
; }
131 * Returns the count of hard references only. Uses a memory barrier.
132 * Used for testing the cache. Regular clients won't need this.
134 int32_t getHardRefCount() const;
137 * If noHardReferences() == TRUE then this object has no hard references.
138 * Must be called only from within the internals of UnifiedCache.
140 inline UBool
noHardReferences() const { return getHardRefCount() == 0; }
143 * If hasHardReferences() == TRUE then this object has hard references.
144 * Must be called only from within the internals of UnifiedCache.
146 inline UBool
hasHardReferences() const { return getHardRefCount() != 0; }
149 * If noSoftReferences() == TRUE then this object has no soft references.
150 * Must be called only from within the internals of UnifiedCache and
151 * only while the cache global mutex is held.
153 UBool
noSoftReferences() const { return (softRefCount
== 0); }
156 * Deletes this object if it has no references or soft references.
158 void deleteIfZeroRefCount() const;
161 * @internal For UnifedCache use only to register this object with itself.
162 * Must be called before this object is exposed to multiple threads.
164 void registerWithCache(const UnifiedCacheBase
*ptr
) const {
169 * Returns a writable version of ptr.
170 * If there is exactly one owner, then ptr itself is returned as a
172 * If there are multiple owners, then ptr is replaced with a
173 * copy-constructed clone,
174 * and that is returned.
175 * Returns NULL if cloning failed.
177 * T must be a subclass of SharedObject.
180 static T
*copyOnWrite(const T
*&ptr
) {
182 if(p
->getRefCount() <= 1) { return const_cast<T
*>(p
); }
184 if(p2
== NULL
) { return NULL
; }
192 * Makes dest an owner of the object pointed to by src while adjusting
193 * reference counts and deleting the previous object dest pointed to
194 * if necessary. Before this call is made, dest must either be NULL or
195 * be included in the reference count of the object it points to.
197 * T must be a subclass of SharedObject.
200 static void copyPtr(const T
*src
, const T
*&dest
) {
202 if(dest
!= NULL
) { dest
->removeRef(); }
204 if(src
!= NULL
) { src
->addRef(); }
209 * Equivalent to copyPtr(NULL, dest).
212 static void clearPtr(const T
*&ptr
) {
220 mutable u_atomic_int32_t totalRefCount
;
222 // Any thread modifying softRefCount must hold the global cache mutex
223 mutable int32_t softRefCount
;
225 mutable u_atomic_int32_t hardRefCount
;
226 mutable const UnifiedCacheBase
*cachePtr
;
227 void addRef(UBool withCacheLock
) const;
228 void removeRef(UBool withCacheLock
) const;