/* ****************************************************************************** * Copyright (C) 2014, International Business Machines * Corporation and others. All Rights Reserved. ****************************************************************************** * sharedobject.h */ #ifndef __SHAREDOBJECT_H__ #define __SHAREDOBJECT_H__ #include "unicode/uobject.h" #include "umutex.h" U_NAMESPACE_BEGIN /** * Base class for shared, reference-counted, auto-deleted objects. * Subclasses can be immutable. * If they are mutable, then they must implement their copy constructor * so that copyOnWrite() works. * * Either stack-allocate, use LocalPointer, or use addRef()/removeRef(). * Sharing requires reference-counting. */ class U_COMMON_API SharedObject : public UObject { public: /** Initializes refCount to 0. */ SharedObject() : refCount(0) {} /** Initializes refCount to 0. */ SharedObject(const SharedObject &other) : UObject(other), refCount(0) {} virtual ~SharedObject(); /** * Increments the number of references to this object. Thread-safe. */ void addRef() const; /** * Decrements the number of references to this object, * and auto-deletes "this" if the number becomes 0. Thread-safe. */ void removeRef() const; /** * Returns the reference counter. Uses a memory barrier. */ int32_t getRefCount() const; void deleteIfZeroRefCount() const; /** * Returns a writable version of ptr. * If there is exactly one owner, then ptr itself is returned as a * non-const pointer. * If there are multiple owners, then ptr is replaced with a * copy-constructed clone, * and that is returned. * Returns NULL if cloning failed. * * T must be a subclass of SharedObject. */ template static T *copyOnWrite(const T *&ptr) { const T *p = ptr; if(p->getRefCount() <= 1) { return const_cast(p); } T *p2 = new T(*p); if(p2 == NULL) { return NULL; } p->removeRef(); ptr = p2; p2->addRef(); return p2; } /** * Makes dest an owner of the object pointed to by src while adjusting * reference counts and deleting the previous object dest pointed to * if necessary. Before this call is made, dest must either be NULL or * be included in the reference count of the object it points to. * * T must be a subclass of SharedObject. */ template static void copyPtr(const T *src, const T *&dest) { if(src != dest) { if(dest != NULL) { dest->removeRef(); } dest = src; if(src != NULL) { src->addRef(); } } } /** * Equivalent to copyPtr(NULL, dest). */ template static void clearPtr(const T *&ptr) { if (ptr != NULL) { ptr->removeRef(); ptr = NULL; } } private: mutable u_atomic_int32_t refCount; }; U_NAMESPACE_END #endif