Skip to content

Commit 8ed08bc

Browse files
committed
[llvm][ADT] Implement IntrusiveRefCntPtr::useCount() (llvm#65502)
This function has the same semantics as `std::shared_ptr<T>::use_count()`, and enables implementing copy-on-write semantics.
1 parent 207b4ce commit 8ed08bc

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

llvm/include/llvm/ADT/IntrusiveRefCntPtr.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ template <class Derived> class RefCountedBase {
9393
#endif
9494

9595
public:
96+
unsigned UseCount() const { return RefCount; }
97+
9698
void Retain() const { ++RefCount; }
9799

98100
void Release() const {
@@ -124,6 +126,8 @@ template <class Derived> class ThreadSafeRefCountedBase {
124126
#endif
125127

126128
public:
129+
unsigned UseCount() const { return RefCount.load(std::memory_order_relaxed); }
130+
127131
void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }
128132

129133
void Release() const {
@@ -155,6 +159,7 @@ template <class Derived> class ThreadSafeRefCountedBase {
155159
/// Bar.h could use IntrusiveRefCntPtr<Foo>, although it still couldn't call any
156160
/// functions on Foo itself, because Foo would be an incomplete type.
157161
template <typename T> struct IntrusiveRefCntPtrInfo {
162+
static unsigned useCount(const T *obj) { return obj->UseCount(); }
158163
static void retain(T *obj) { obj->Retain(); }
159164
static void release(T *obj) { obj->Release(); }
160165
};
@@ -213,6 +218,10 @@ template <typename T> class IntrusiveRefCntPtr {
213218

214219
void resetWithoutRelease() { Obj = nullptr; }
215220

221+
unsigned useCount() const {
222+
return Obj ? IntrusiveRefCntPtrInfo<T>::useCount(Obj) : 0;
223+
}
224+
216225
private:
217226
void retain() {
218227
if (Obj)

llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,4 +140,17 @@ TEST(IntrusiveRefCntPtr, InteropsWithConvertible) {
140140
EXPECT_EQ(P4, X4.get());
141141
}
142142

143+
TEST(IntrusiveRefCntPtrTest, Unique) {
144+
IntrusiveRefCntPtr<X> X1;
145+
EXPECT_EQ(X1.useCount(), 0);
146+
X1 = new X();
147+
EXPECT_EQ(X1.useCount(), 1);
148+
{
149+
IntrusiveRefCntPtr<X> X2 = X1;
150+
EXPECT_EQ(X1.useCount(), 2);
151+
EXPECT_EQ(X2.useCount(), 2);
152+
}
153+
EXPECT_EQ(X1.useCount(), 1);
154+
}
155+
143156
} // end namespace llvm

0 commit comments

Comments
 (0)