]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/sharedobject.h
ICU-531.30.tar.gz
[apple/icu.git] / icuSources / common / sharedobject.h
diff --git a/icuSources/common/sharedobject.h b/icuSources/common/sharedobject.h
new file mode 100644 (file)
index 0000000..671bab1
--- /dev/null
@@ -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<typename T>
+    static T *copyOnWrite(const T *&ptr) {
+        const T *p = ptr;
+        if(p->getRefCount() <= 1) { return const_cast<T *>(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<typename T>
+    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<typename T>
+    static void clearPtr(const T *&ptr) {
+        if (ptr != NULL) {
+            ptr->removeRef();
+            ptr = NULL;
+        }
+    }
+
+private:
+    mutable u_atomic_int32_t refCount;
+};
+
+U_NAMESPACE_END
+
+#endif