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 refCount to 0. */ SharedObject()30 SharedObject() : refCount(0) {} 31 32 /** Initializes refCount to 0. */ SharedObject(const SharedObject &)33 SharedObject(const SharedObject &/*other*/) : refCount(0) {} 34 virtual ~SharedObject(); 35 36 /** 37 * Increments the number of references to this object. Thread-safe. 38 */ 39 void addRef() const; 40 41 /** 42 * Decrements the number of references to this object, 43 * and auto-deletes "this" if the number becomes 0. Thread-safe. 44 */ 45 void removeRef() const; 46 47 /** 48 * Returns the reference counter. Uses a memory barrier. 49 */ 50 int32_t getRefCount() const; 51 52 void deleteIfZeroRefCount() const; 53 54 /** 55 * Returns a writable version of ptr. 56 * If there is exactly one owner, then ptr itself is returned as a 57 * non-const pointer. 58 * If there are multiple owners, then ptr is replaced with a 59 * copy-constructed clone, 60 * and that is returned. 61 * Returns NULL if cloning failed. 62 * 63 * T must be a subclass of SharedObject. 64 */ 65 template<typename T> copyOnWrite(const T * & ptr)66 static T *copyOnWrite(const T *&ptr) { 67 const T *p = ptr; 68 if(p->getRefCount() <= 1) { return const_cast<T *>(p); } 69 T *p2 = new T(*p); 70 if(p2 == NULL) { return NULL; } 71 p->removeRef(); 72 ptr = p2; 73 p2->addRef(); 74 return p2; 75 } 76 77 /** 78 * Makes dest an owner of the object pointed to by src while adjusting 79 * reference counts and deleting the previous object dest pointed to 80 * if necessary. Before this call is made, dest must either be NULL or 81 * own its object. 82 * 83 * T must be a subclass of SharedObject. 84 */ 85 template<typename T> copyPtr(const T * src,const T * & dest)86 static void copyPtr(const T *src, const T *&dest) { 87 if(src != dest) { 88 if(dest != NULL) { dest->removeRef(); } 89 dest = src; 90 if(src != NULL) { src->addRef(); } 91 } 92 } 93 94 /** 95 * Equivalent to copy(NULL, dest). 96 */ 97 template<typename T> clearPtr(const T * & ptr)98 static void clearPtr(const T *&ptr) { 99 if (ptr != NULL) { 100 ptr->removeRef(); 101 ptr = NULL; 102 } 103 } 104 105 private: 106 mutable u_atomic_int32_t refCount; 107 }; 108 109 U_NAMESPACE_END 110 111 #endif 112