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