Skip to content

Commit

Permalink
[llvm][ADT] Implement IntrusiveRefCntPtr::useCount() (llvm#65502)
Browse files Browse the repository at this point in the history
This function has the same semantics as
`std::shared_ptr<T>::use_count()`, and enables implementing
copy-on-write semantics.
  • Loading branch information
jansvoboda11 authored Sep 6, 2023
1 parent d015e48 commit d148767
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 0 deletions.
9 changes: 9 additions & 0 deletions llvm/include/llvm/ADT/IntrusiveRefCntPtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ template <class Derived> class RefCountedBase {
#endif

public:
unsigned UseCount() const { return RefCount; }

void Retain() const { ++RefCount; }

void Release() const {
Expand Down Expand Up @@ -124,6 +126,8 @@ template <class Derived> class ThreadSafeRefCountedBase {
#endif

public:
unsigned UseCount() const { return RefCount.load(std::memory_order_relaxed); }

void Retain() const { RefCount.fetch_add(1, std::memory_order_relaxed); }

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

void resetWithoutRelease() { Obj = nullptr; }

unsigned useCount() const {
return Obj ? IntrusiveRefCntPtrInfo<T>::useCount(Obj) : 0;
}

private:
void retain() {
if (Obj)
Expand Down
13 changes: 13 additions & 0 deletions llvm/unittests/ADT/IntrusiveRefCntPtrTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,17 @@ TEST(IntrusiveRefCntPtr, InteropsWithConvertible) {
EXPECT_EQ(P4, X4.get());
}

TEST(IntrusiveRefCntPtrTest, Unique) {
IntrusiveRefCntPtr<X> X1;
EXPECT_EQ(X1.useCount(), 0);
X1 = new X();
EXPECT_EQ(X1.useCount(), 1);
{
IntrusiveRefCntPtr<X> X2 = X1;
EXPECT_EQ(X1.useCount(), 2);
EXPECT_EQ(X2.useCount(), 2);
}
EXPECT_EQ(X1.useCount(), 1);
}

} // end namespace llvm

0 comments on commit d148767

Please sign in to comment.