X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/08b89b0a244153b9f5bbb2f49c55ab0f7298122e..b331163bffd790ced0e88b73f44f86d49ccc48a5:/icuSources/common/sharedptr.h diff --git a/icuSources/common/sharedptr.h b/icuSources/common/sharedptr.h deleted file mode 100644 index 31d62aae..00000000 --- a/icuSources/common/sharedptr.h +++ /dev/null @@ -1,225 +0,0 @@ -/* -******************************************************************************* -* Copyright (C) 2014, International Business Machines Corporation and -* others. All Rights Reserved. -******************************************************************************* -* -* File SHAREDPTR.H -******************************************************************************* -*/ - -#ifndef __SHARED_PTR_H__ -#define __SHARED_PTR_H__ - -#include "unicode/uobject.h" -#include "umutex.h" -#include "uassert.h" - -U_NAMESPACE_BEGIN - -// Wrap u_atomic_int32_t in a UMemory so that we allocate them in the same -// way we allocate all other ICU objects. -struct AtomicInt : public UMemory { - u_atomic_int32_t value; -}; - -/** - * SharedPtr are shared pointers that support copy-on-write sematics. - * SharedPtr makes the act of copying large objects cheap by deferring the - * cost of the copy to the first write operation after the copy. - * - * A SharedPtr instance can refer to no object or an object of type T. - * T must have a clone() method that copies - * the object and returns a pointer to the copy. Copy and assignment of - * SharedPtr instances are cheap because they only involve copying or - * assigning the SharedPtr instance, not the T object which could be large. - * Although many SharedPtr instances may refer to the same T object, - * clients can still assume that each SharedPtr instance has its own - * private instance of T because each SharedPtr instance offers only a - * const view of its T object through normal pointer operations. If a caller - * must change a T object through its SharedPtr, it can do so by calling - * readWrite() on the SharedPtr instance. readWrite() ensures that the - * SharedPtr really does have its own private T object by cloning it if - * it is shared by using its clone() method. SharedPtr instances handle - * management by reference counting their T objects. T objects that are - * referenced by no SharedPtr instances get deleted automatically. - */ - -// TODO (Travis Keep): Leave interface the same, but find a more efficient -// implementation that is easier to understand. -template -class SharedPtr { -public: - /** - * Constructor. If there is a memory allocation error creating - * reference counter then this object will contain NULL, and adopted - * pointer will be freed. Note that when passing NULL or no argument to - * constructor, no memory allocation error can happen as NULL pointers - * are never reference counted. - */ - explicit SharedPtr(T *adopted=NULL) : ptr(adopted), refPtr(NULL) { - if (ptr != NULL) { - refPtr = new AtomicInt(); - if (refPtr == NULL) { - delete ptr; - ptr = NULL; - } else { - refPtr->value = 1; - } - } - } - - /** - * Copy constructor. - */ - SharedPtr(const SharedPtr &other) : - ptr(other.ptr), refPtr(other.refPtr) { - if (refPtr != NULL) { - umtx_atomic_inc(&refPtr->value); - } - } - - /** - * assignment operator. - */ - SharedPtr &operator=(const SharedPtr &other) { - if (ptr != other.ptr) { - SharedPtr newValue(other); - swap(newValue); - } - return *this; - } - - /** - * Destructor. - */ - ~SharedPtr() { - if (refPtr != NULL) { - if (umtx_atomic_dec(&refPtr->value) == 0) { - delete ptr; - delete refPtr; - } - } - } - - /** - * reset adopts a new pointer. On success, returns TRUE. - * On memory allocation error creating reference counter for adopted - * pointer, returns FALSE while leaving this instance unchanged. - */ - bool reset(T *adopted) { - SharedPtr newValue(adopted); - if (adopted != NULL && newValue.ptr == NULL) { - // We couldn't allocate ref counter. - return FALSE; - } - swap(newValue); - return TRUE; - } - - /** - * reset makes this instance refer to no object. - */ - void reset() { - reset(NULL); - } - - /** - * count returns how many SharedPtr instances, including this one, - * refer to the T object. Used for testing. Clients need not use in - * practice. - */ - int32_t count() const { - if (refPtr == NULL) { - return 0; - } - return umtx_loadAcquire(refPtr->value); - } - - /** - * Swaps this instance with other. - */ - void swap(SharedPtr &other) { - T *tempPtr = other.ptr; - AtomicInt *tempRefPtr = other.refPtr; - other.ptr = ptr; - other.refPtr = refPtr; - ptr = tempPtr; - refPtr = tempRefPtr; - } - - const T *operator->() const { - return ptr; - } - - const T &operator*() const { - return *ptr; - } - - bool operator==(const T *other) const { - return ptr == other; - } - - bool operator!=(const T *other) const { - return ptr != other; - } - - /** - * readOnly gives const access to this instance's T object. If this - * instance refers to no object, returns NULL. - */ - const T *readOnly() const { - return ptr; - } - - /** - * readWrite returns a writable pointer to its T object copying it first - * using its clone() method if it is shared. - * On memory allocation error or if this instance refers to no object, - * this method returns NULL leaving this instance unchanged. - *

- * If readWrite() returns a non NULL pointer, it guarantees that this - * object holds the only reference to its T object enabling the caller to - * perform mutations using the returned pointer without affecting other - * SharedPtr objects. However, the non-constness of readWrite continues as - * long as the returned pointer is in scope. Therefore it is an API - * violation to call readWrite() on A; perform B = A; and then proceed to - * mutate A via its writeable pointer as that would be the same as setting - * B = A while A is changing. The returned pointer is guaranteed to be - * valid only while this object is in scope because this object maintains - * ownership of its T object. Therefore, callers must never attempt to - * delete the returned writeable pointer. The best practice with readWrite - * is this: callers should use the returned pointer from readWrite() only - * within the same scope as that call to readWrite, and that scope should - * be made as small as possible avoiding overlap with other operatios on - * this object. - */ - T *readWrite() { - int32_t refCount = count(); - if (refCount <= 1) { - return ptr; - } - T *result = (T *) ptr->clone(); - if (result == NULL) { - // Memory allocation error - return NULL; - } - if (!reset(result)) { - return NULL; - } - return ptr; - } -private: - T *ptr; - AtomicInt *refPtr; - // No heap allocation. Use only stack. - static void * U_EXPORT2 operator new(size_t size); - static void * U_EXPORT2 operator new[](size_t size); -#if U_HAVE_PLACEMENT_NEW - static void * U_EXPORT2 operator new(size_t, void *ptr); -#endif -}; - -U_NAMESPACE_END - -#endif