Coverage Report

Created: 2025-11-11 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/keystone/llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
Line
Count
Source
1
//== llvm/ADT/IntrusiveRefCntPtr.h - Smart Refcounting Pointer ---*- C++ -*-==//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file defines IntrusiveRefCntPtr, a template class that
11
// implements a "smart" pointer for objects that maintain their own
12
// internal reference count, and RefCountedBase/RefCountedBaseVPTR, two
13
// generic base classes for objects that wish to have their lifetimes
14
// managed using reference counting.
15
//
16
// IntrusiveRefCntPtr is similar to Boost's intrusive_ptr with added
17
// LLVM-style casting.
18
//
19
//===----------------------------------------------------------------------===//
20
21
#ifndef LLVM_ADT_INTRUSIVEREFCNTPTR_H
22
#define LLVM_ADT_INTRUSIVEREFCNTPTR_H
23
24
#include <atomic>
25
#include <cassert>
26
#include <cstddef>
27
28
namespace llvm_ks {
29
30
  template <class T>
31
  class IntrusiveRefCntPtr;
32
33
//===----------------------------------------------------------------------===//
34
/// RefCountedBase - A generic base class for objects that wish to
35
///  have their lifetimes managed using reference counts. Classes
36
///  subclass RefCountedBase to obtain such functionality, and are
37
///  typically handled with IntrusiveRefCntPtr "smart pointers" (see below)
38
///  which automatically handle the management of reference counts.
39
///  Objects that subclass RefCountedBase should not be allocated on
40
///  the stack, as invoking "delete" (which is called when the
41
///  reference count hits 0) on such objects is an error.
42
//===----------------------------------------------------------------------===//
43
  template <class Derived>
44
  class RefCountedBase {
45
    mutable unsigned ref_cnt;
46
47
  public:
48
    RefCountedBase() : ref_cnt(0) {}
49
    RefCountedBase(const RefCountedBase &) : ref_cnt(0) {}
50
51
0
    void Retain() const { ++ref_cnt; }
Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::DirIterState>::Retain() const
Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::RecDirIterState>::Retain() const
52
0
    void Release() const {
53
0
      assert (ref_cnt > 0 && "Reference count is already zero.");
54
0
      if (--ref_cnt == 0) delete static_cast<const Derived*>(this);
55
0
    }
Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::DirIterState>::Release() const
Unexecuted instantiation: llvm_ks::RefCountedBase<llvm_ks::sys::fs::detail::RecDirIterState>::Release() const
56
  };
57
58
//===----------------------------------------------------------------------===//
59
/// RefCountedBaseVPTR - A class that has the same function as
60
///  RefCountedBase, but with a virtual destructor. Should be used
61
///  instead of RefCountedBase for classes that already have virtual
62
///  methods to enforce dynamic allocation via 'new'. Classes that
63
///  inherit from RefCountedBaseVPTR can't be allocated on stack -
64
///  attempting to do this will produce a compile error.
65
//===----------------------------------------------------------------------===//
66
  class RefCountedBaseVPTR {
67
    mutable unsigned ref_cnt;
68
69
  protected:
70
0
    RefCountedBaseVPTR() : ref_cnt(0) {}
71
0
    RefCountedBaseVPTR(const RefCountedBaseVPTR &) : ref_cnt(0) {}
72
73
0
    virtual ~RefCountedBaseVPTR() {}
74
75
0
    void Retain() const { ++ref_cnt; }
76
0
    void Release() const {
77
0
      assert (ref_cnt > 0 && "Reference count is already zero.");
78
0
      if (--ref_cnt == 0) delete this;
79
0
    }
80
81
    template <typename T>
82
    friend struct IntrusiveRefCntPtrInfo;
83
  };
84
85
86
  template <typename T> struct IntrusiveRefCntPtrInfo {
87
0
    static void retain(T *obj) { obj->Retain(); }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::DirIterState>::retain(llvm_ks::sys::fs::detail::DirIterState*)
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::RecDirIterState>::retain(llvm_ks::sys::fs::detail::RecDirIterState*)
88
0
    static void release(T *obj) { obj->Release(); }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::DirIterState>::release(llvm_ks::sys::fs::detail::DirIterState*)
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtrInfo<llvm_ks::sys::fs::detail::RecDirIterState>::release(llvm_ks::sys::fs::detail::RecDirIterState*)
89
  };
90
91
/// \brief A thread-safe version of \c llvm_ks::RefCountedBase.
92
///
93
/// A generic base class for objects that wish to have their lifetimes managed
94
/// using reference counts. Classes subclass \c ThreadSafeRefCountedBase to
95
/// obtain such functionality, and are typically handled with
96
/// \c IntrusiveRefCntPtr "smart pointers" which automatically handle the
97
/// management of reference counts.
98
template <class Derived>
99
class ThreadSafeRefCountedBase {
100
  mutable std::atomic<int> RefCount;
101
102
protected:
103
  ThreadSafeRefCountedBase() : RefCount(0) {}
104
105
public:
106
  void Retain() const { ++RefCount; }
107
108
  void Release() const {
109
    int NewRefCount = --RefCount;
110
    assert(NewRefCount >= 0 && "Reference count was already zero.");
111
    if (NewRefCount == 0)
112
      delete static_cast<const Derived*>(this);
113
  }
114
};
115
116
//===----------------------------------------------------------------------===//
117
/// IntrusiveRefCntPtr - A template class that implements a "smart pointer"
118
///  that assumes the wrapped object has a reference count associated
119
///  with it that can be managed via calls to
120
///  IntrusivePtrAddRef/IntrusivePtrRelease.  The smart pointers
121
///  manage reference counts via the RAII idiom: upon creation of
122
///  smart pointer the reference count of the wrapped object is
123
///  incremented and upon destruction of the smart pointer the
124
///  reference count is decremented.  This class also safely handles
125
///  wrapping NULL pointers.
126
///
127
/// Reference counting is implemented via calls to
128
///  Obj->Retain()/Obj->Release(). Release() is required to destroy
129
///  the object when the reference count reaches zero. Inheriting from
130
///  RefCountedBase/RefCountedBaseVPTR takes care of this
131
///  automatically.
132
//===----------------------------------------------------------------------===//
133
  template <typename T>
134
  class IntrusiveRefCntPtr {
135
    T* Obj;
136
137
  public:
138
    typedef T element_type;
139
140
    explicit IntrusiveRefCntPtr() : Obj(nullptr) {}
141
142
    IntrusiveRefCntPtr(T* obj) : Obj(obj) {
143
      retain();
144
    }
145
146
    IntrusiveRefCntPtr(const IntrusiveRefCntPtr& S) : Obj(S.Obj) {
147
      retain();
148
    }
149
150
    IntrusiveRefCntPtr(IntrusiveRefCntPtr&& S) : Obj(S.Obj) {
151
      S.Obj = nullptr;
152
    }
153
154
    template <class X>
155
    IntrusiveRefCntPtr(IntrusiveRefCntPtr<X>&& S) : Obj(S.get()) {
156
      S.Obj = nullptr;
157
    }
158
159
    template <class X>
160
    IntrusiveRefCntPtr(const IntrusiveRefCntPtr<X>& S)
161
      : Obj(S.get()) {
162
      retain();
163
    }
164
165
0
    IntrusiveRefCntPtr& operator=(IntrusiveRefCntPtr S) {
166
0
      swap(S);
167
0
      return *this;
168
0
    }
169
170
    ~IntrusiveRefCntPtr() { release(); }
171
172
0
    T& operator*() const { return *Obj; }
173
174
0
    T* operator->() const { return Obj; }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::operator->() const
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::operator->() const
175
176
0
    T* get() const { return Obj; }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::get() const
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::get() const
177
178
0
    explicit operator bool() const { return Obj; }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::operator bool() const
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::operator bool() const
179
180
0
    void swap(IntrusiveRefCntPtr& other) {
181
0
      T* tmp = other.Obj;
182
0
      other.Obj = Obj;
183
0
      Obj = tmp;
184
0
    }
185
186
0
    void reset() {
187
0
      release();
188
0
      Obj = nullptr;
189
0
    }
190
191
    void resetWithoutRelease() {
192
      Obj = nullptr;
193
    }
194
195
  private:
196
0
    void retain() { if (Obj) IntrusiveRefCntPtrInfo<T>::retain(Obj); }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::retain()
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::retain()
197
0
    void release() { if (Obj) IntrusiveRefCntPtrInfo<T>::release(Obj); }
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState>::release()
Unexecuted instantiation: llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState>::release()
198
199
    template <typename X>
200
    friend class IntrusiveRefCntPtr;
201
  };
202
203
  template<class T, class U>
204
  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
205
                         const IntrusiveRefCntPtr<U>& B)
206
0
  {
207
0
    return A.get() == B.get();
208
0
  }
Unexecuted instantiation: bool llvm_ks::operator==<llvm_ks::sys::fs::detail::DirIterState, llvm_ks::sys::fs::detail::DirIterState>(llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState> const&, llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::DirIterState> const&)
Unexecuted instantiation: bool llvm_ks::operator==<llvm_ks::sys::fs::detail::RecDirIterState, llvm_ks::sys::fs::detail::RecDirIterState>(llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState> const&, llvm_ks::IntrusiveRefCntPtr<llvm_ks::sys::fs::detail::RecDirIterState> const&)
209
210
  template<class T, class U>
211
  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
212
                         const IntrusiveRefCntPtr<U>& B)
213
  {
214
    return A.get() != B.get();
215
  }
216
217
  template<class T, class U>
218
  inline bool operator==(const IntrusiveRefCntPtr<T>& A,
219
                         U* B)
220
  {
221
    return A.get() == B;
222
  }
223
224
  template<class T, class U>
225
  inline bool operator!=(const IntrusiveRefCntPtr<T>& A,
226
                         U* B)
227
  {
228
    return A.get() != B;
229
  }
230
231
  template<class T, class U>
232
  inline bool operator==(T* A,
233
                         const IntrusiveRefCntPtr<U>& B)
234
  {
235
    return A == B.get();
236
  }
237
238
  template<class T, class U>
239
  inline bool operator!=(T* A,
240
                         const IntrusiveRefCntPtr<U>& B)
241
  {
242
    return A != B.get();
243
  }
244
245
  template <class T>
246
  bool operator==(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
247
    return !B;
248
  }
249
250
  template <class T>
251
  bool operator==(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
252
    return B == A;
253
  }
254
255
  template <class T>
256
  bool operator!=(std::nullptr_t A, const IntrusiveRefCntPtr<T> &B) {
257
    return !(A == B);
258
  }
259
260
  template <class T>
261
  bool operator!=(const IntrusiveRefCntPtr<T> &A, std::nullptr_t B) {
262
    return !(A == B);
263
  }
264
265
//===----------------------------------------------------------------------===//
266
// LLVM-style downcasting support for IntrusiveRefCntPtr objects
267
//===----------------------------------------------------------------------===//
268
269
  template <typename From> struct simplify_type;
270
271
  template<class T> struct simplify_type<IntrusiveRefCntPtr<T> > {
272
    typedef T* SimpleType;
273
    static SimpleType getSimplifiedValue(IntrusiveRefCntPtr<T>& Val) {
274
      return Val.get();
275
    }
276
  };
277
278
  template<class T> struct simplify_type<const IntrusiveRefCntPtr<T> > {
279
    typedef /*const*/ T* SimpleType;
280
    static SimpleType getSimplifiedValue(const IntrusiveRefCntPtr<T>& Val) {
281
      return Val.get();
282
    }
283
  };
284
285
} // end namespace llvm_ks
286
287
#endif // LLVM_ADT_INTRUSIVEREFCNTPTR_H