Skip to content

Commit f2c39f6

Browse files
committed
Add sp<T>::numReferences method to allow checking reference count
1 parent 21412a3 commit f2c39f6

2 files changed

Lines changed: 69 additions & 0 deletions

File tree

include/alloc/pointer.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,10 @@ class sp {
371371
return (SpPointerType)type;
372372
}
373373

374+
int numReferences() const {
375+
return details ? details->refs.load(std::memory_order_acquire) : 0;
376+
}
377+
374378
private:
375379
sp_pointer_details_t* details; /**< Pointer to the control block. */
376380
char type = NULLPTR; /**< Current ownership model type. */

src/tests/test_pointer.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,68 @@ TEST(SpTest, DoesNotCollapseOnTemplatedMove) {
311311

312312
EXPECT_FALSE(b->collapsed) << "Constructor sp(U&&) was incorrectly used instead of templated move constructor";
313313
}
314+
315+
TEST(SpTest, NumReferences) {
316+
sp<int> a;
317+
EXPECT_EQ(a.numReferences(), 0);
318+
319+
sp<int> b(10);
320+
EXPECT_EQ(b.numReferences(), 1);
321+
322+
sp<int> c = b;
323+
EXPECT_EQ(b.numReferences(), 2);
324+
EXPECT_EQ(c.numReferences(), 2);
325+
326+
{
327+
sp<int> d = c;
328+
EXPECT_EQ(b.numReferences(), 3);
329+
EXPECT_EQ(c.numReferences(), 3);
330+
EXPECT_EQ(d.numReferences(), 3);
331+
}
332+
333+
EXPECT_EQ(b.numReferences(), 2);
334+
EXPECT_EQ(c.numReferences(), 2);
335+
336+
b.reset();
337+
EXPECT_EQ(b.numReferences(), 0);
338+
EXPECT_EQ(c.numReferences(), 1);
339+
}
340+
341+
TEST(SpTest, NumReferencesWithCOW) {
342+
sp<int> a(SpPointerType::UNIQUE, 5);
343+
EXPECT_EQ(a.numReferences(), 1);
344+
345+
sp<int> b = a;
346+
EXPECT_EQ(a.numReferences(), 2);
347+
EXPECT_EQ(b.numReferences(), 2);
348+
349+
b.mut() = 10; // Should detach
350+
EXPECT_EQ(a.numReferences(), 1);
351+
EXPECT_EQ(b.numReferences(), 1);
352+
}
353+
354+
TEST(SpTest, NumReferencesWithMove) {
355+
sp<int> a(5);
356+
EXPECT_EQ(a.numReferences(), 1);
357+
358+
sp<int> b(std::move(a));
359+
EXPECT_EQ(a.numReferences(), 0);
360+
EXPECT_EQ(b.numReferences(), 1);
361+
}
362+
363+
TEST(SpTest, NumReferencesWithTemplatedCopyMove) {
364+
struct Base { virtual ~Base() {} };
365+
struct Derived : Base {};
366+
367+
sp<Derived> d = sp<Derived>::create();
368+
EXPECT_EQ(d.numReferences(), 1);
369+
370+
sp<Base> b(d);
371+
EXPECT_EQ(d.numReferences(), 2);
372+
EXPECT_EQ(b.numReferences(), 2);
373+
374+
sp<Base> b2(std::move(d));
375+
EXPECT_EQ(d.numReferences(), 0);
376+
EXPECT_EQ(b.numReferences(), 2);
377+
EXPECT_EQ(b2.numReferences(), 2);
378+
}

0 commit comments

Comments
 (0)