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 16U_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 */ 27class U_COMMON_API SharedObject : public UObject { 28public: 29 /** Initializes refCount to 0. */ 30 SharedObject() : refCount(0) {} 31 32 /** Initializes refCount to 0. */ 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> 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> 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> 98 static void clearPtr(const T *&ptr) { 99 if (ptr != NULL) { 100 ptr->removeRef(); 101 ptr = NULL; 102 } 103 } 104 105private: 106 mutable u_atomic_int32_t refCount; 107}; 108 109U_NAMESPACE_END 110 111#endif 112