Coverage Report

Created: 2026-01-22 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/common/sharedobject.h
Line
Count
Source
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
******************************************************************************
5
* Copyright (C) 2015-2016, International Business Machines
6
* Corporation and others.  All Rights Reserved.
7
******************************************************************************
8
* sharedobject.h
9
*/
10
11
#ifndef __SHAREDOBJECT_H__
12
#define __SHAREDOBJECT_H__
13
14
15
#include "unicode/uobject.h"
16
#include "umutex.h"
17
18
U_NAMESPACE_BEGIN
19
20
class SharedObject;
21
22
/**
23
 * Base class for unified cache exposing enough methods to SharedObject
24
 * instances to allow their addRef() and removeRef() methods to
25
 * update cache metrics. No other part of ICU, except for SharedObject,
26
 * should directly call the methods of this base class.
27
 */
28
class U_COMMON_API UnifiedCacheBase : public UObject {
29
public:
30
9
    UnifiedCacheBase() { }
31
32
    /**
33
     * Notify the cache implementation that an object was seen transitioning to
34
     * zero hard references. The cache may use this to keep track the number of
35
     * unreferenced SharedObjects, and to trigger evictions.
36
     */
37
    virtual void handleUnreferencedObject() const = 0;
38
39
    virtual ~UnifiedCacheBase();
40
private:
41
    UnifiedCacheBase(const UnifiedCacheBase &) = delete;
42
    UnifiedCacheBase &operator=(const UnifiedCacheBase &) = delete;
43
};
44
45
/**
46
 * Base class for shared, reference-counted, auto-deleted objects.
47
 * Subclasses can be immutable.
48
 * If they are mutable, then they must implement their copy constructor
49
 * so that copyOnWrite() works.
50
 *
51
 * Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
52
 * Sharing requires reference-counting.
53
 */
54
class U_COMMON_API_CLASS SharedObject : public UObject {
55
public:
56
    /** Initializes totalRefCount, softRefCount to 0. */
57
    U_COMMON_API SharedObject() :
58
71.8k
            softRefCount(0),
59
71.8k
            hardRefCount(0),
60
71.8k
            cachePtr(nullptr) {}
61
62
    /** Initializes totalRefCount, softRefCount to 0. */
63
    U_COMMON_API SharedObject(const SharedObject &other) :
64
14.5k
            UObject(other),
65
14.5k
            softRefCount(0),
66
14.5k
            hardRefCount(0),
67
14.5k
            cachePtr(nullptr) {}
68
69
    U_COMMON_API virtual ~SharedObject();
70
71
    /**
72
     * Increments the number of hard references to this object. Thread-safe.
73
     * Not for use from within the Unified Cache implementation.
74
     */
75
    U_COMMON_API void addRef() const;
76
77
    /**
78
     * Decrements the number of hard references to this object, and
79
     * arrange for possible cache-eviction and/or deletion if ref
80
     * count goes to zero. Thread-safe.
81
     * 
82
     * Not for use from within the UnifiedCache implementation.
83
     */
84
    U_COMMON_API void removeRef() const;
85
86
    /**
87
     * Returns the number of hard references for this object.
88
     * Uses a memory barrier.
89
     */
90
    U_COMMON_API int32_t getRefCount() const;
91
92
    /**
93
     * If noHardReferences() == true then this object has no hard references.
94
     * Must be called only from within the internals of UnifiedCache.
95
     */
96
101k
    U_COMMON_API inline UBool noHardReferences() const { return getRefCount() == 0; }
97
98
    /**
99
     * If hasHardReferences() == true then this object has hard references.
100
     * Must be called only from within the internals of UnifiedCache.
101
     */
102
0
    U_COMMON_API inline UBool hasHardReferences() const { return getRefCount() != 0; }
103
104
    /**
105
     * Deletes this object if it has no references.
106
     * Available for non-cached SharedObjects only. Ownership of cached objects
107
     * is with the UnifiedCache, which is solely responsible for eviction and deletion.
108
     */
109
    U_COMMON_API void deleteIfZeroRefCount() const;
110
111
        
112
    /**
113
     * Returns a writable version of ptr.
114
     * If there is exactly one owner, then ptr itself is returned as a
115
     *  non-const pointer.
116
     * If there are multiple owners, then ptr is replaced with a 
117
     * copy-constructed clone,
118
     * and that is returned.
119
     * Returns nullptr if cloning failed.
120
     *
121
     * T must be a subclass of SharedObject.
122
     */
123
    template<typename T>
124
14.6k
    static T *copyOnWrite(const T *&ptr) {
125
14.6k
        const T *p = ptr;
126
14.6k
        if(p->getRefCount() <= 1) { return const_cast<T *>(p); }
127
14.5k
        T *p2 = new T(*p);
128
14.5k
        if(p2 == nullptr) { return nullptr; }
129
14.5k
        p->removeRef();
130
14.5k
        ptr = p2;
131
14.5k
        p2->addRef();
132
14.5k
        return p2;
133
14.5k
    }
134
135
    /**
136
     * Makes dest an owner of the object pointed to by src while adjusting
137
     * reference counts and deleting the previous object dest pointed to
138
     * if necessary. Before this call is made, dest must either be nullptr or
139
     * be included in the reference count of the object it points to. 
140
     *
141
     * T must be a subclass of SharedObject.
142
     */
143
    template<typename T>
144
527k
    static void copyPtr(const T *src, const T *&dest) {
145
527k
        if(src != dest) {
146
527k
            if(dest != nullptr) { dest->removeRef(); }
147
527k
            dest = src;
148
527k
            if(src != nullptr) { src->addRef(); }
149
527k
        }
150
527k
    }
void icu_79::SharedObject::copyPtr<icu_79::RelativeDateTimeCacheData>(icu_79::RelativeDateTimeCacheData const*, icu_79::RelativeDateTimeCacheData const*&)
Line
Count
Source
144
2.10k
    static void copyPtr(const T *src, const T *&dest) {
145
2.10k
        if(src != dest) {
146
2.10k
            if(dest != nullptr) { dest->removeRef(); }
147
2.10k
            dest = src;
148
2.10k
            if(src != nullptr) { src->addRef(); }
149
2.10k
        }
150
2.10k
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedNumberFormat>(icu_79::SharedNumberFormat const*, icu_79::SharedNumberFormat const*&)
Line
Count
Source
144
147k
    static void copyPtr(const T *src, const T *&dest) {
145
147k
        if(src != dest) {
146
147k
            if(dest != nullptr) { dest->removeRef(); }
147
147k
            dest = src;
148
147k
            if(src != nullptr) { src->addRef(); }
149
147k
        }
150
147k
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedPluralRules>(icu_79::SharedPluralRules const*, icu_79::SharedPluralRules const*&)
Line
Count
Source
144
21.1k
    static void copyPtr(const T *src, const T *&dest) {
145
21.1k
        if(src != dest) {
146
21.1k
            if(dest != nullptr) { dest->removeRef(); }
147
21.1k
            dest = src;
148
21.1k
            if(src != nullptr) { src->addRef(); }
149
21.1k
        }
150
21.1k
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedBreakIterator>(icu_79::SharedBreakIterator const*, icu_79::SharedBreakIterator const*&)
Line
Count
Source
144
167
    static void copyPtr(const T *src, const T *&dest) {
145
167
        if(src != dest) {
146
167
            if(dest != nullptr) { dest->removeRef(); }
147
167
            dest = src;
148
167
            if(src != nullptr) { src->addRef(); }
149
167
        }
150
167
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedCalendar>(icu_79::SharedCalendar const*, icu_79::SharedCalendar const*&)
Line
Count
Source
144
171k
    static void copyPtr(const T *src, const T *&dest) {
145
171k
        if(src != dest) {
146
171k
            if(dest != nullptr) { dest->removeRef(); }
147
171k
            dest = src;
148
171k
            if(src != nullptr) { src->addRef(); }
149
171k
        }
150
171k
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedDateFormatSymbols>(icu_79::SharedDateFormatSymbols const*, icu_79::SharedDateFormatSymbols const*&)
Line
Count
Source
144
124k
    static void copyPtr(const T *src, const T *&dest) {
145
124k
        if(src != dest) {
146
124k
            if(dest != nullptr) { dest->removeRef(); }
147
124k
            dest = src;
148
124k
            if(src != nullptr) { src->addRef(); }
149
124k
        }
150
124k
    }
Unexecuted instantiation: void icu_79::SharedObject::copyPtr<icu_79::CollationSettings>(icu_79::CollationSettings const*, icu_79::CollationSettings const*&)
void icu_79::SharedObject::copyPtr<icu_79::CollationCacheEntry>(icu_79::CollationCacheEntry const*, icu_79::CollationCacheEntry const*&)
Line
Count
Source
144
18.5k
    static void copyPtr(const T *src, const T *&dest) {
145
18.5k
        if(src != dest) {
146
18.5k
            if(dest != nullptr) { dest->removeRef(); }
147
18.5k
            dest = src;
148
18.5k
            if(src != nullptr) { src->addRef(); }
149
18.5k
        }
150
18.5k
    }
void icu_79::SharedObject::copyPtr<icu_79::SharedObject>(icu_79::SharedObject const*, icu_79::SharedObject const*&)
Line
Count
Source
144
321
    static void copyPtr(const T *src, const T *&dest) {
145
321
        if(src != dest) {
146
321
            if(dest != nullptr) { dest->removeRef(); }
147
321
            dest = src;
148
321
            if(src != nullptr) { src->addRef(); }
149
321
        }
150
321
    }
void icu_79::SharedObject::copyPtr<icu_79::DateFmtBestPattern>(icu_79::DateFmtBestPattern const*, icu_79::DateFmtBestPattern const*&)
Line
Count
Source
144
40.3k
    static void copyPtr(const T *src, const T *&dest) {
145
40.3k
        if(src != dest) {
146
40.3k
            if(dest != nullptr) { dest->removeRef(); }
147
40.3k
            dest = src;
148
40.3k
            if(src != nullptr) { src->addRef(); }
149
40.3k
        }
150
40.3k
    }
151
152
    /**
153
     * Equivalent to copyPtr(nullptr, dest).
154
     */
155
    template<typename T>
156
618k
    static void clearPtr(const T *&ptr) {
157
618k
        if (ptr != nullptr) {
158
569k
            ptr->removeRef();
159
569k
            ptr = nullptr;
160
569k
        }
161
618k
    }
void icu_79::SharedObject::clearPtr<icu_79::RelativeDateTimeCacheData>(icu_79::RelativeDateTimeCacheData const*&)
Line
Count
Source
156
2.10k
    static void clearPtr(const T *&ptr) {
157
2.10k
        if (ptr != nullptr) {
158
2.10k
            ptr->removeRef();
159
2.10k
            ptr = nullptr;
160
2.10k
        }
161
2.10k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedBreakIterator>(icu_79::SharedBreakIterator const*&)
Line
Count
Source
156
1.93k
    static void clearPtr(const T *&ptr) {
157
1.93k
        if (ptr != nullptr) {
158
0
            ptr->removeRef();
159
0
            ptr = nullptr;
160
0
        }
161
1.93k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedCalendar>(icu_79::SharedCalendar const*&)
Line
Count
Source
156
171k
    static void clearPtr(const T *&ptr) {
157
171k
        if (ptr != nullptr) {
158
171k
            ptr->removeRef();
159
171k
            ptr = nullptr;
160
171k
        }
161
171k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedDateFormatSymbols>(icu_79::SharedDateFormatSymbols const*&)
Line
Count
Source
156
125k
    static void clearPtr(const T *&ptr) {
157
125k
        if (ptr != nullptr) {
158
124k
            ptr->removeRef();
159
124k
            ptr = nullptr;
160
124k
        }
161
125k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedNumberFormat>(icu_79::SharedNumberFormat const*&)
Line
Count
Source
156
183k
    static void clearPtr(const T *&ptr) {
157
183k
        if (ptr != nullptr) {
158
144k
            ptr->removeRef();
159
144k
            ptr = nullptr;
160
144k
        }
161
183k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedPluralRules>(icu_79::SharedPluralRules const*&)
Line
Count
Source
156
19.0k
    static void clearPtr(const T *&ptr) {
157
19.0k
        if (ptr != nullptr) {
158
19.0k
            ptr->removeRef();
159
19.0k
            ptr = nullptr;
160
19.0k
        }
161
19.0k
    }
void icu_79::SharedObject::clearPtr<icu_79::CollationSettings>(icu_79::CollationSettings const*&)
Line
Count
Source
156
28.7k
    static void clearPtr(const T *&ptr) {
157
28.7k
        if (ptr != nullptr) {
158
25.1k
            ptr->removeRef();
159
25.1k
            ptr = nullptr;
160
25.1k
        }
161
28.7k
    }
void icu_79::SharedObject::clearPtr<icu_79::CollationCacheEntry>(icu_79::CollationCacheEntry const*&)
Line
Count
Source
156
39.5k
    static void clearPtr(const T *&ptr) {
157
39.5k
        if (ptr != nullptr) {
158
35.9k
            ptr->removeRef();
159
35.9k
            ptr = nullptr;
160
35.9k
        }
161
39.5k
    }
void icu_79::SharedObject::clearPtr<icu_79::CollationTailoring>(icu_79::CollationTailoring const*&)
Line
Count
Source
156
4.19k
    static void clearPtr(const T *&ptr) {
157
4.19k
        if (ptr != nullptr) {
158
4.19k
            ptr->removeRef();
159
4.19k
            ptr = nullptr;
160
4.19k
        }
161
4.19k
    }
void icu_79::SharedObject::clearPtr<icu_79::SharedObject>(icu_79::SharedObject const*&)
Line
Count
Source
156
1.52k
    static void clearPtr(const T *&ptr) {
157
1.52k
        if (ptr != nullptr) {
158
1.52k
            ptr->removeRef();
159
1.52k
            ptr = nullptr;
160
1.52k
        }
161
1.52k
    }
void icu_79::SharedObject::clearPtr<icu_79::DateFmtBestPattern>(icu_79::DateFmtBestPattern const*&)
Line
Count
Source
156
40.3k
    static void clearPtr(const T *&ptr) {
157
40.3k
        if (ptr != nullptr) {
158
40.3k
            ptr->removeRef();
159
40.3k
            ptr = nullptr;
160
40.3k
        }
161
40.3k
    }
162
163
private:
164
    /**
165
     * The number of references from the UnifiedCache, which is
166
     * the number of times that the sharedObject is stored as a hash table value.
167
     * For use by UnifiedCache implementation code only.
168
     * All access is synchronized by UnifiedCache's gCacheMutex
169
     */
170
    mutable int32_t softRefCount;
171
    friend class UnifiedCache;
172
173
    /**
174
     * Reference count, excluding references from within the UnifiedCache implementation.
175
     */
176
    mutable u_atomic_int32_t hardRefCount;
177
    
178
    mutable const UnifiedCacheBase *cachePtr;
179
180
};
181
182
U_NAMESPACE_END
183
184
#endif