File indexing completed on 2026-05-10 08:43:07
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060 #ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
0061 #define LLVM_ADT_INTRUSIVEREFCNTPTR_H
0062
0063 #include <atomic>
0064 #include <cassert>
0065 #include <cstddef>
0066 #include <memory>
0067
0068 namespace llvm {
0069
0070
0071
0072
0073
0074
0075
0076 template <class Derived> class RefCountedBase {
0077 mutable unsigned RefCount = 0;
0078
0079 protected:
0080 RefCountedBase() = default;
0081 RefCountedBase(const RefCountedBase &) {}
0082 RefCountedBase &operator=(const RefCountedBase &) = delete;
0083
0084 #ifndef NDEBUG
0085 ~RefCountedBase() {
0086 assert(RefCount == 0 &&
0087 "Destruction occurred when there are still references to this.");
0088 }
0089 #else
0090
0091
0092 ~RefCountedBase() = default;
0093 #endif
0094
0095 public:
0096 unsigned UseCount() const { return RefCount; }
0097
0098 void Retain() const { ++RefCount; }
0099
0100 void Release() const {
0101 assert(RefCount > 0 && "Reference count is already zero.");
0102 if (--RefCount == 0)
0103 delete static_cast<const Derived *>(this);
0104 }
0105 };
0106
0107
0108 template <class Derived> class ThreadSafeRefCountedBase {
0109 mutable std::atomic<int> RefCount{0};
0110
0111 protected:
0112 ThreadSafeRefCountedBase() = default;
0113 ThreadSafeRefCountedBase(const ThreadSafeRefCountedBase &) {}
0114 ThreadSafeRefCountedBase &
0115 operator=(const ThreadSafeRefCountedBase &) = delete;
0116
0117 #ifndef NDEBUG
0118 ~ThreadSafeRefCountedBase() {
0119 assert(RefCount == 0 &&
0120 "Destruction occurred when there are still references to this.");
0121 }
0122 #else
0123
0124
0125 ~ThreadSafeRefCountedBase() = default;
0126 #endif
0127
0128 public:
0129 unsigned UseCount() const { return RefCount.load(std::memory_order_relaxed); }
0130
0131 void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }
0132
0133 void Release() const {
0134 int NewRefCount = RefCount.fetch_sub(1, std::memory_order_acq_rel) - 1;
0135 assert(NewRefCount >= 0 && "Reference count was already zero.");
0136 if (NewRefCount == 0)
0137 delete static_cast<const Derived *>(this);
0138 }
0139 };
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161 template <typename T> struct IntrusiveRefCntPtrInfo {
0162 static unsigned useCount(const T *obj) { return obj->UseCount(); }
0163 static void retain(T *obj) { obj->Retain(); }
0164 static void release(T *obj) { obj->Release(); }
0165 };
0166
0167
0168
0169
0170
0171
0172
0173 template <typename T> class IntrusiveRefCntPtr {
0174 T *Obj = nullptr;
0175
0176 public:
0177 using element_type = T;
0178
0179 explicit IntrusiveRefCntPtr() = default;
0180 IntrusiveRefCntPtr(T *obj) : Obj(obj) { retain(); }
0181 IntrusiveRefCntPtr(const IntrusiveRefCntPtr &S) : Obj(S.Obj) { retain(); }
0182 IntrusiveRefCntPtr(IntrusiveRefCntPtr &&S) : Obj(S.Obj) { S.Obj = nullptr; }
0183
0184 template <class X,
0185 std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true>
0186 IntrusiveRefCntPtr(IntrusiveRefCntPtr<X> S) : Obj(S.get()) {
0187 S.Obj = nullptr;
0188 }
0189
0190 template <class X,
0191 std::enable_if_t<std::is_convertible<X *, T *>::value, bool> = true>
0192 IntrusiveRefCntPtr(std::unique_ptr<X> S) : Obj(S.release()) {
0193 retain();
0194 }
0195
0196 ~IntrusiveRefCntPtr() { release(); }
0197
0198 IntrusiveRefCntPtr &operator=(IntrusiveRefCntPtr S) {
0199 swap(S);
0200 return *this;
0201 }
0202
0203 T &operator*() const { return *Obj; }
0204 T *operator->() const { return Obj; }
0205 T *get() const { return Obj; }
0206 explicit operator bool() const { return Obj; }
0207
0208 void swap(IntrusiveRefCntPtr &other) {
0209 T *tmp = other.Obj;
0210 other.Obj = Obj;
0211 Obj = tmp;
0212 }
0213
0214 void reset() {
0215 release();
0216 Obj = nullptr;
0217 }
0218
0219 void resetWithoutRelease() { Obj = nullptr; }
0220
0221 unsigned useCount() const {
0222 return Obj ? IntrusiveRefCntPtrInfo<T>::useCount(Obj) : 0;
0223 }
0224
0225 private:
0226 void retain() {
0227 if (Obj)
0228 IntrusiveRefCntPtrInfo<T>::retain(Obj);
0229 }
0230
0231 void release() {
0232 if (Obj)
0233 IntrusiveRefCntPtrInfo<T>::release(Obj);
0234 }
0235
0236 template <typename X> friend class IntrusiveRefCntPtr;
0237 };
0238
0239 template <class T, class U>
0240 inline bool operator==(const IntrusiveRefCntPtr<T> &A,
0241 const IntrusiveRefCntPtr<U> &B) {
0242 return A.get() == B.get();
0243 }
0244
0245 template <class T, class U>
0246 inline bool operator!=(const IntrusiveRefCntPtr<T> &A,
0247 const IntrusiveRefCntPtr<U> &B) {
0248 return A.get() != B.get();
0249 }
0250
0251 template <class T, class U>
0252 inline bool operator==(const IntrusiveRefCntPtr<T> &A, U *B) {
0253 return A.get() == B;
0254 }
0255
0256 template <class T, class U>
0257 inline bool operator!=(const IntrusiveRefCntPtr<T> &A, U *B) {
0258 return A.get() != B;
0259 }
0260
0261 template <class T, class U>
0262 inline bool operator==(T *A, const IntrusiveRefCntPtr<U> &B) {
0263 return A == B.get();
0264 }
0265
0266 template <class T, class U>
0267 inline bool operator!=(T *A, const IntrusiveRefCntPtr<U> &B) {
0268 return A != B.get();
0269 }
0270
0271 template <class T>
0272 bool operator==(std::nullptr_t, const IntrusiveRefCntPtr<T> &B) {
0273 return !B;
0274 }
0275
0276 template <class T>
0277 bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
0278 return B == A;
0279 }
0280
0281 template <class T>
0282 bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
0283 return !(A == B);
0284 }
0285
0286 template <class T>
0287 bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
0288 return !(A == B);
0289 }
0290
0291
0292
0293 template <typename From> struct simplify_type;
0294
0295 template <class T> struct simplify_type<IntrusiveRefCntPtr<T>> {
0296 using SimpleType = T *;
0297
0298 static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T> &Val) {
0299 return Val.get();
0300 }
0301 };
0302
0303 template <class T> struct simplify_type<const IntrusiveRefCntPtr<T>> {
0304 using SimpleType = T *;
0305
0306 static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T> &Val) {
0307 return Val.get();
0308 }
0309 };
0310
0311
0312 template <typename T, typename... Args>
0313 IntrusiveRefCntPtr<T> makeIntrusiveRefCnt(Args &&...A) {
0314 return IntrusiveRefCntPtr<T>(new T(std::forward<Args>(A)...));
0315 }
0316
0317 }
0318
0319 #endif