X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/efa1e6592fb03ce23b15276b2b91d885a3ee7da5..57a6839dcb3bba09e8228b822b290604668416fe:/icuSources/common/sharedobject.h diff --git a/icuSources/common/sharedobject.h b/icuSources/common/sharedobject.h new file mode 100644 index 00000000..671bab13 --- /dev/null +++ b/icuSources/common/sharedobject.h @@ -0,0 +1,111 @@ +/* +****************************************************************************** +* 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*/) : 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 + * own its object. + * + * 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 copy(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