Coverage Report

Created: 2025-10-24 06:54

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
72.1k
            softRefCount(0),
59
72.1k
            hardRefCount(0),
60
72.1k
            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
102k
    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
473k
    static void copyPtr(const T *src, const T *&dest) {
145
473k
        if(src != dest) {
146
473k
            if(dest != nullptr) { dest->removeRef(); }
147
473k
            dest = src;
148
473k
            if(src != nullptr) { src->addRef(); }
149
473k
        }
150
473k
    }
void icu_78::SharedObject::copyPtr<icu_78::RelativeDateTimeCacheData>(icu_78::RelativeDateTimeCacheData const*, icu_78::RelativeDateTimeCacheData const*&)
Line
Count
Source
144
2.21k
    static void copyPtr(const T *src, const T *&dest) {
145
2.21k
        if(src != dest) {
146
2.21k
            if(dest != nullptr) { dest->removeRef(); }
147
2.21k
            dest = src;
148
2.21k
            if(src != nullptr) { src->addRef(); }
149
2.21k
        }
150
2.21k
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedNumberFormat>(icu_78::SharedNumberFormat const*, icu_78::SharedNumberFormat const*&)
Line
Count
Source
144
129k
    static void copyPtr(const T *src, const T *&dest) {
145
129k
        if(src != dest) {
146
129k
            if(dest != nullptr) { dest->removeRef(); }
147
129k
            dest = src;
148
129k
            if(src != nullptr) { src->addRef(); }
149
129k
        }
150
129k
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedPluralRules>(icu_78::SharedPluralRules const*, icu_78::SharedPluralRules const*&)
Line
Count
Source
144
21.0k
    static void copyPtr(const T *src, const T *&dest) {
145
21.0k
        if(src != dest) {
146
21.0k
            if(dest != nullptr) { dest->removeRef(); }
147
21.0k
            dest = src;
148
21.0k
            if(src != nullptr) { src->addRef(); }
149
21.0k
        }
150
21.0k
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedBreakIterator>(icu_78::SharedBreakIterator const*, icu_78::SharedBreakIterator const*&)
Line
Count
Source
144
202
    static void copyPtr(const T *src, const T *&dest) {
145
202
        if(src != dest) {
146
202
            if(dest != nullptr) { dest->removeRef(); }
147
202
            dest = src;
148
202
            if(src != nullptr) { src->addRef(); }
149
202
        }
150
202
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedCalendar>(icu_78::SharedCalendar const*, icu_78::SharedCalendar const*&)
Line
Count
Source
144
157k
    static void copyPtr(const T *src, const T *&dest) {
145
157k
        if(src != dest) {
146
157k
            if(dest != nullptr) { dest->removeRef(); }
147
157k
            dest = src;
148
157k
            if(src != nullptr) { src->addRef(); }
149
157k
        }
150
157k
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedDateFormatSymbols>(icu_78::SharedDateFormatSymbols const*, icu_78::SharedDateFormatSymbols const*&)
Line
Count
Source
144
109k
    static void copyPtr(const T *src, const T *&dest) {
145
109k
        if(src != dest) {
146
109k
            if(dest != nullptr) { dest->removeRef(); }
147
109k
            dest = src;
148
109k
            if(src != nullptr) { src->addRef(); }
149
109k
        }
150
109k
    }
Unexecuted instantiation: void icu_78::SharedObject::copyPtr<icu_78::CollationSettings>(icu_78::CollationSettings const*, icu_78::CollationSettings const*&)
void icu_78::SharedObject::copyPtr<icu_78::CollationCacheEntry>(icu_78::CollationCacheEntry const*, icu_78::CollationCacheEntry const*&)
Line
Count
Source
144
19.9k
    static void copyPtr(const T *src, const T *&dest) {
145
19.9k
        if(src != dest) {
146
19.9k
            if(dest != nullptr) { dest->removeRef(); }
147
19.9k
            dest = src;
148
19.9k
            if(src != nullptr) { src->addRef(); }
149
19.9k
        }
150
19.9k
    }
void icu_78::SharedObject::copyPtr<icu_78::SharedObject>(icu_78::SharedObject const*, icu_78::SharedObject const*&)
Line
Count
Source
144
322
    static void copyPtr(const T *src, const T *&dest) {
145
322
        if(src != dest) {
146
322
            if(dest != nullptr) { dest->removeRef(); }
147
322
            dest = src;
148
322
            if(src != nullptr) { src->addRef(); }
149
322
        }
150
322
    }
void icu_78::SharedObject::copyPtr<icu_78::DateFmtBestPattern>(icu_78::DateFmtBestPattern const*, icu_78::DateFmtBestPattern const*&)
Line
Count
Source
144
32.7k
    static void copyPtr(const T *src, const T *&dest) {
145
32.7k
        if(src != dest) {
146
32.7k
            if(dest != nullptr) { dest->removeRef(); }
147
32.7k
            dest = src;
148
32.7k
            if(src != nullptr) { src->addRef(); }
149
32.7k
        }
150
32.7k
    }
151
152
    /**
153
     * Equivalent to copyPtr(nullptr, dest).
154
     */
155
    template<typename T>
156
566k
    static void clearPtr(const T *&ptr) {
157
566k
        if (ptr != nullptr) {
158
516k
            ptr->removeRef();
159
516k
            ptr = nullptr;
160
516k
        }
161
566k
    }
void icu_78::SharedObject::clearPtr<icu_78::RelativeDateTimeCacheData>(icu_78::RelativeDateTimeCacheData const*&)
Line
Count
Source
156
2.21k
    static void clearPtr(const T *&ptr) {
157
2.21k
        if (ptr != nullptr) {
158
2.21k
            ptr->removeRef();
159
2.21k
            ptr = nullptr;
160
2.21k
        }
161
2.21k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedBreakIterator>(icu_78::SharedBreakIterator const*&)
Line
Count
Source
156
2.01k
    static void clearPtr(const T *&ptr) {
157
2.01k
        if (ptr != nullptr) {
158
0
            ptr->removeRef();
159
0
            ptr = nullptr;
160
0
        }
161
2.01k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedCalendar>(icu_78::SharedCalendar const*&)
Line
Count
Source
156
157k
    static void clearPtr(const T *&ptr) {
157
157k
        if (ptr != nullptr) {
158
157k
            ptr->removeRef();
159
157k
            ptr = nullptr;
160
157k
        }
161
157k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedDateFormatSymbols>(icu_78::SharedDateFormatSymbols const*&)
Line
Count
Source
156
110k
    static void clearPtr(const T *&ptr) {
157
110k
        if (ptr != nullptr) {
158
109k
            ptr->removeRef();
159
109k
            ptr = nullptr;
160
109k
        }
161
110k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedNumberFormat>(icu_78::SharedNumberFormat const*&)
Line
Count
Source
156
166k
    static void clearPtr(const T *&ptr) {
157
166k
        if (ptr != nullptr) {
158
126k
            ptr->removeRef();
159
126k
            ptr = nullptr;
160
126k
        }
161
166k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedPluralRules>(icu_78::SharedPluralRules const*&)
Line
Count
Source
156
18.8k
    static void clearPtr(const T *&ptr) {
157
18.8k
        if (ptr != nullptr) {
158
18.8k
            ptr->removeRef();
159
18.8k
            ptr = nullptr;
160
18.8k
        }
161
18.8k
    }
void icu_78::SharedObject::clearPtr<icu_78::CollationSettings>(icu_78::CollationSettings const*&)
Line
Count
Source
156
29.2k
    static void clearPtr(const T *&ptr) {
157
29.2k
        if (ptr != nullptr) {
158
25.6k
            ptr->removeRef();
159
25.6k
            ptr = nullptr;
160
25.6k
        }
161
29.2k
    }
void icu_78::SharedObject::clearPtr<icu_78::CollationCacheEntry>(icu_78::CollationCacheEntry const*&)
Line
Count
Source
156
41.5k
    static void clearPtr(const T *&ptr) {
157
41.5k
        if (ptr != nullptr) {
158
37.9k
            ptr->removeRef();
159
37.9k
            ptr = nullptr;
160
37.9k
        }
161
41.5k
    }
void icu_78::SharedObject::clearPtr<icu_78::CollationTailoring>(icu_78::CollationTailoring const*&)
Line
Count
Source
156
4.18k
    static void clearPtr(const T *&ptr) {
157
4.18k
        if (ptr != nullptr) {
158
4.18k
            ptr->removeRef();
159
4.18k
            ptr = nullptr;
160
4.18k
        }
161
4.18k
    }
void icu_78::SharedObject::clearPtr<icu_78::SharedObject>(icu_78::SharedObject const*&)
Line
Count
Source
156
1.53k
    static void clearPtr(const T *&ptr) {
157
1.53k
        if (ptr != nullptr) {
158
1.53k
            ptr->removeRef();
159
1.53k
            ptr = nullptr;
160
1.53k
        }
161
1.53k
    }
void icu_78::SharedObject::clearPtr<icu_78::DateFmtBestPattern>(icu_78::DateFmtBestPattern const*&)
Line
Count
Source
156
32.7k
    static void clearPtr(const T *&ptr) {
157
32.7k
        if (ptr != nullptr) {
158
32.7k
            ptr->removeRef();
159
32.7k
            ptr = nullptr;
160
32.7k
        }
161
32.7k
    }
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