1fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/* 2fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2014, International Business Machines 4fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Corporation and others. All Rights Reserved. 5fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius****************************************************************************** 6fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* sharedobject.h 7fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius*/ 8fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 9fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#ifndef __SHAREDOBJECT_H__ 10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define __SHAREDOBJECT_H__ 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 12fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 13fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/uobject.h" 14fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "umutex.h" 15fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 16fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_BEGIN 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 18fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius/** 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Base class for shared, reference-counted, auto-deleted objects. 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Subclasses can be immutable. 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If they are mutable, then they must implement their copy constructor 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * so that copyOnWrite() works. 23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Either stack-allocate, use LocalPointer, or use addRef()/removeRef(). 25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Sharing requires reference-counting. 26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass U_COMMON_API SharedObject : public UObject { 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic: 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** Initializes refCount to 0. */ 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject() : refCount(0) {} 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** Initializes refCount to 0. */ 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject(const SharedObject &/*other*/) : refCount(0) {} 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius virtual ~SharedObject(); 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Increments the number of references to this object. Thread-safe. 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void addRef() const; 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Decrements the number of references to this object, 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * and auto-deletes "this" if the number becomes 0. Thread-safe. 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void removeRef() const; 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Returns the reference counter. Uses a memory barrier. 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t getRefCount() const; 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void deleteIfZeroRefCount() const; 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 55fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Returns a writable version of ptr. 56fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If there is exactly one owner, then ptr itself is returned as a 57fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * non-const pointer. 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * If there are multiple owners, then ptr is replaced with a 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * copy-constructed clone, 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * and that is returned. 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Returns NULL if cloning failed. 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * T must be a subclass of SharedObject. 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static T *copyOnWrite(const T *&ptr) { 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const T *p = ptr; 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(p->getRefCount() <= 1) { return const_cast<T *>(p); } 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius T *p2 = new T(*p); 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(p2 == NULL) { return NULL; } 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius p->removeRef(); 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr = p2; 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius p2->addRef(); 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return p2; 75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Makes dest an owner of the object pointed to by src while adjusting 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * reference counts and deleting the previous object dest pointed to 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * if necessary. Before this call is made, dest must either be NULL or 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * own its object. 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * T must be a subclass of SharedObject. 84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static void copyPtr(const T *src, const T *&dest) { 87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(src != dest) { 88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(dest != NULL) { dest->removeRef(); } 89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest = src; 90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if(src != NULL) { src->addRef(); } 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius /** 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius * Equivalent to copy(NULL, dest). 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius */ 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius template<typename T> 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static void clearPtr(const T *&ptr) { 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (ptr != NULL) { 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr->removeRef(); 101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ptr = NULL; 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate: 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius mutable u_atomic_int32_t refCount; 107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_NAMESPACE_END 110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif 112