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