| /* |
| * Copyright 2022 Rive |
| */ |
| |
| #include <rive/refcnt.hpp> |
| #include <catch.hpp> |
| #include <cstdio> |
| |
| using namespace rive; |
| |
| class MyRefCnt : public RefCnt<MyRefCnt> |
| { |
| public: |
| MyRefCnt() {} |
| MyRefCnt(int, float, bool) {} |
| |
| void require_count(int value) { REQUIRE(this->debugging_refcnt() == value); } |
| }; |
| |
| TEST_CASE("refcnt", "[basics]") |
| { |
| MyRefCnt my; |
| REQUIRE(my.debugging_refcnt() == 1); |
| my.ref(); |
| REQUIRE(my.debugging_refcnt() == 2); |
| my.unref(); |
| REQUIRE(my.debugging_refcnt() == 1); |
| |
| safe_ref(&my); |
| REQUIRE(my.debugging_refcnt() == 2); |
| safe_unref(&my); |
| REQUIRE(my.debugging_refcnt() == 1); |
| |
| // just exercise these to be sure they don't crash |
| safe_ref((MyRefCnt*)nullptr); |
| safe_unref((MyRefCnt*)nullptr); |
| } |
| |
| TEST_CASE("rcp", "[basics]") |
| { |
| rcp<MyRefCnt> r0(nullptr); |
| |
| REQUIRE(r0.get() == nullptr); |
| REQUIRE(!r0); |
| |
| auto r1 = make_rcp<MyRefCnt>(); |
| REQUIRE(r1.get() != nullptr); |
| REQUIRE(r1); |
| REQUIRE(r1 != r0); |
| REQUIRE(r1->debugging_refcnt() == 1); |
| |
| auto r2 = r1; |
| REQUIRE(r1.get() == r2.get()); |
| REQUIRE(r1 == r2); |
| REQUIRE(r2->debugging_refcnt() == 2); |
| |
| auto r3 = make_rcp<MyRefCnt>(1, .5f, false); |
| REQUIRE(r3.get() != nullptr); |
| REQUIRE(r3); |
| REQUIRE(r3 != r1); |
| REQUIRE(r3->debugging_refcnt() == 1); |
| |
| auto ptr = r2.release(); |
| REQUIRE(r2.get() == nullptr); |
| REQUIRE(r1.get() == ptr); |
| |
| // This is important, calling release() does not modify the ref count on the object |
| // We have to manage that explicit since we called release() |
| REQUIRE(r1->debugging_refcnt() == 2); |
| ptr->unref(); |
| REQUIRE(r1->debugging_refcnt() == 1); |
| |
| r1.reset(); |
| REQUIRE(r1.get() == nullptr); |
| |
| struct A : public rive::RefCnt<A> |
| { |
| int x = 17; |
| }; |
| struct B : public A |
| { |
| int y = 21; |
| }; |
| auto b = make_rcp<B>(); |
| CHECK(b->y == 21); |
| rcp<A> a = b; |
| CHECK(a->x == 17); |
| CHECK(static_rcp_cast<B>(a)->y == 21); |
| CHECK(rcp<A>(b)->x == 17); |
| CHECK(a->debugging_refcnt() == 2); |
| CHECK(b->debugging_refcnt() == 2); |
| CHECK(static_rcp_cast<B>(std::move(a))->y == 21); |
| CHECK(a == nullptr); |
| CHECK(b->debugging_refcnt() == 1); |
| a = ref_rcp(b.get()); |
| CHECK(b == a); |
| CHECK(a->debugging_refcnt() == 2); |
| CHECK(a->x == 17); |
| CHECK(static_rcp_cast<B>(a)->y == 21); |
| } |