1 /* 2 ****************************************************************************** 3 * Copyright (C) 2014, International Business Machines 4 * Corporation and others. All Rights Reserved. 5 ****************************************************************************** 6 * sharedobject.h 7 */ 8 9 #ifndef __SHAREDOBJECT_H__ 10 #define __SHAREDOBJECT_H__ 11 12 13 #include "unicode/uobject.h" 14 #include "umutex.h" 15 16 U_NAMESPACE_BEGIN 17 18 /** 19 * Base class for shared, reference-counted, auto-deleted objects. 20 * Subclasses can be immutable. 21 * If they are mutable, then they must implement their copy constructor 22 * so that copyOnWrite() works. 23 * 24 * Either stack-allocate, use LocalPointer, or use addRef()/removeRef(). 25 * Sharing requires reference-counting. 26 */ 27 class U_COMMON_API SharedObject : public UObject { 28 public: 29 /** Initializes totalRefCount, softRefCount to 0. */ SharedObject()30 SharedObject() : totalRefCount(0), softRefCount(0) {} 31 32 /** Initializes totalRefCount, softRefCount to 0. */ SharedObject(const SharedObject & other)33 SharedObject(const SharedObject &other) 34 : UObject(other), 35 totalRefCount(0), 36 softRefCount(0) {} 37 38 virtual ~SharedObject(); 39 40 /** 41 * Increments the number of references to this object. Thread-safe. 42 */ 43 void addRef() const; 44 45 /** 46 * Increments the number of soft references to this object. Thread-safe. 47 */ 48 void addSoftRef() const; 49 50 /** 51 * Decrements the number of references to this object. Thread-safe. 52 */ 53 void removeRef() const; 54 55 /** 56 * Decrements the number of soft references to this object. Thread-safe. 57 */ 58 void removeSoftRef() const; 59 60 /** 61 * Returns the reference counter including soft references. 62 * Uses a memory barrier. 63 */ 64 int32_t getRefCount() const; 65 66 /** 67 * Returns the count of soft references only. Uses a memory barrier. 68 * Used for testing the cache. Regular clients won't need this. 69 */ 70 int32_t getSoftRefCount() const; 71 72 /** 73 * If allSoftReferences() == TRUE then this object has only soft 74 * references. The converse is not necessarily true. 75 */ 76 UBool allSoftReferences() const; 77 78 /** 79 * Deletes this object if it has no references or soft references. 80 */ 81 void deleteIfZeroRefCount() const; 82 83 /** 84 * Returns a writable version of ptr. 85 * If there is exactly one owner, then ptr itself is returned as a 86 * non-const pointer. 87 * If there are multiple owners, then ptr is replaced with a 88 * copy-constructed clone, 89 * and that is returned. 90 * Returns NULL if cloning failed. 91 * 92 * T must be a subclass of SharedObject. 93 */ 94 template<typename T> copyOnWrite(const T * & ptr)95 static T *copyOnWrite(const T *&ptr) { 96 const T *p = ptr; 97 if(p->getRefCount() <= 1) { return const_cast<T *>(p); } 98 T *p2 = new T(*p); 99 if(p2 == NULL) { return NULL; } 100 p->removeRef(); 101 ptr = p2; 102 p2->addRef(); 103 return p2; 104 } 105 106 /** 107 * Makes dest an owner of the object pointed to by src while adjusting 108 * reference counts and deleting the previous object dest pointed to 109 * if necessary. Before this call is made, dest must either be NULL or 110 * be included in the reference count of the object it points to. 111 * 112 * T must be a subclass of SharedObject. 113 */ 114 template<typename T> copyPtr(const T * src,const T * & dest)115 static void copyPtr(const T *src, const T *&dest) { 116 if(src != dest) { 117 if(dest != NULL) { dest->removeRef(); } 118 dest = src; 119 if(src != NULL) { src->addRef(); } 120 } 121 } 122 123 /** 124 * Equivalent to copyPtr(NULL, dest). 125 */ 126 template<typename T> clearPtr(const T * & ptr)127 static void clearPtr(const T *&ptr) { 128 if (ptr != NULL) { 129 ptr->removeRef(); 130 ptr = NULL; 131 } 132 } 133 134 private: 135 mutable u_atomic_int32_t totalRefCount; 136 mutable u_atomic_int32_t softRefCount; 137 }; 138 139 U_NAMESPACE_END 140 141 #endif 142