summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorStanislaw Halik <sthalik@misaki.pl>2024-05-05 01:07:46 +0200
committerStanislaw Halik <sthalik@misaki.pl>2024-05-05 03:31:21 +0200
commit965e81a6bfc1d91041d2af32bf459a76d8c42fc8 (patch)
tree11c9713f48ca62c5f44340a7d2660113922a0e71
parent474794432e854ac3838eab152bb8ab25f3b4fad0 (diff)
aa
-rw-r--r--compat/borrowed-ptr-fwd.hpp2
-rw-r--r--compat/borrowed-ptr.inl9
-rw-r--r--test/bptr.cpp192
3 files changed, 200 insertions, 3 deletions
diff --git a/compat/borrowed-ptr-fwd.hpp b/compat/borrowed-ptr-fwd.hpp
index 01dd20f7..28ea3c55 100644
--- a/compat/borrowed-ptr-fwd.hpp
+++ b/compat/borrowed-ptr-fwd.hpp
@@ -69,4 +69,6 @@ public:
template<typename U, typename Tʹ> friend bptr<U> static_pointer_cast(const bptr<Tʹ>& p) noexcept;
};
+template<typename T> bptr(T* ptr) -> bptr<T>;
+
} // namespace floormat
diff --git a/compat/borrowed-ptr.inl b/compat/borrowed-ptr.inl
index 6b72192c..05724fcd 100644
--- a/compat/borrowed-ptr.inl
+++ b/compat/borrowed-ptr.inl
@@ -5,7 +5,9 @@
#define FM_BPTR_DEBUG
-#if defined FM_BPTR_DEBUG && !defined FM_NO_DEBUG
+#ifdef __CLION_IDE__
+#define fm_bptr_assert(...) (void(__VA_ARGS__))
+#elif defined FM_BPTR_DEBUG && !defined FM_NO_DEBUG
#define fm_bptr_assert(...) fm_assert(__VA_ARGS__)
#else
#define fm_bptr_assert(...) void()
@@ -175,7 +177,8 @@ bptr<T>& bptr<T>::_copy_assign(const bptr<Y>& other) noexcept
blk->decrement(blk);
casted_ptr = other.casted_ptr;
blk = other.blk;
- ++blk->_count;
+ if (blk)
+ ++blk->_count;
}
return *this;
}
@@ -204,7 +207,7 @@ bptr<T>& bptr<T>::_move_assign(bptr<Y>&& other) noexcept
template<typename T> T* bptr<T>::get() const noexcept
{
- if (blk && blk->_ptr)
+ if (blk && blk->_ptr) [[likely]]
{
fm_bptr_assert(casted_ptr);
return casted_ptr;
diff --git a/test/bptr.cpp b/test/bptr.cpp
index 6f823344..55b10fe0 100644
--- a/test/bptr.cpp
+++ b/test/bptr.cpp
@@ -1,6 +1,7 @@
#include "app.hpp"
#include "compat/assert.hpp"
#include "compat/borrowed-ptr.inl"
+#include <array>
namespace floormat {
@@ -94,12 +95,203 @@ void test2()
fm_assert(A_alive == 0);
}
+void test3()
+{
+ A_total = 0; A_alive = 0;
+
+ auto p1 = bptr<A>{InPlace, 3};
+ (void)p1;
+ auto p2 = p1;
+ auto p3 = p2;
+
+ fm_assert(p1.use_count() == 3);
+ fm_assert(p1.get());
+ fm_assert(p1.get() == p2.get());
+ fm_assert(p1.get() == p3.get());
+ fm_assert(A_total == 1);
+ fm_assert(A_alive == 1);
+
+ p3 = nullptr; (void)p3;
+ fm_assert(p1.use_count() == 2);
+ p3 = p2;
+ fm_assert(p1.use_count() == 3 && p3->val == 3 && p3->serial == 1 && p2 == p3 && p1 == p3);
+}
+
+void check_empty(const bptr<A>& p)
+{
+ fm_assert(!p);
+ fm_assert(p.use_count() == 0);
+ fm_assert(!p.get());
+}
+
+void check_nonempty(const bptr<A>& p)
+{
+ fm_assert(p);
+ fm_assert(p.use_count() > 0);
+ fm_assert(p.get());
+}
+
+void test4()
+{
+ A_total = 0; A_alive = 0;
+
+ fm_assert(bptr<A>{} == bptr<A>{nullptr});
+ fm_assert(bptr<A>{} == bptr<A>{(A*)nullptr});
+ fm_assert(A_total == 0 && A_alive == 0);
+
+ {
+ auto p1 = bptr<A>{InPlace, 42};
+ auto p2 = bptr<A>{InPlace, 41};
+ auto p3 = bptr<A>{};
+ check_empty(p3);
+ (void)p1.operator=(p1);
+ (void)p2.operator=(p2);
+ fm_assert(p1->val == 42 && p1->serial == 1);
+ fm_assert(p2->val == 41 && p2->serial == 2);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 2);
+ check_nonempty(p1);
+ check_nonempty(p2);
+
+ p1.swap(p2);
+ fm_assert(p1->val == 41 && p1->serial == 2);
+ fm_assert(p2->val == 42 && p2->serial == 1);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 2);
+ check_nonempty(p1);
+ check_nonempty(p2);
+
+ p1 = nullptr;
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 1);
+ check_empty(p1);
+ check_nonempty(p2);
+
+ (void)p2;
+ p1 = p2;
+ fm_assert(p1 == p2);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 1);
+ check_nonempty(p1);
+ check_nonempty(p2);
+
+ p2 = bptr<A>{(A*)nullptr};
+ check_empty(p2);
+ check_nonempty(p1);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 1);
+ p1.reset();
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 0);
+
+ p1 = p2;
+ p2 = p1;
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 0);
+ }
+}
+
+void test5()
+{
+ A_total = 0; A_alive = 0;
+ auto p1 = bptr<A>{InPlace, -1};
+ auto p2 = bptr<A>{InPlace, -2};
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 2);
+ (void)p1;
+
+ auto p3 = p1;
+ fm_assert(p1.use_count() == 2);
+ fm_assert(p2.use_count() == 1);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 2);
+ fm_assert(p1->serial == 1 && p1->val == -1);
+ fm_assert(p2->serial == 2 && p2->val == -2);
+ fm_assert(p3->serial == 1 && p3->val == -1);
+
+ p1 = nullptr;
+ fm_assert(!p1.get());
+ fm_assert(p2->serial == 2 && p2->val == -2);
+ fm_assert(p3->serial == 1 && p3->val == -1);
+ fm_assert(A_total == 2);
+ fm_assert(A_alive == 2);
+
+ p2 = nullptr;
+ fm_assert(!p1.get());
+ fm_assert(!p2.get());
+ fm_assert(p3->serial == 1 && p3->val == -1);
+}
+
+void test6()
+{
+ constexpr size_t size = 5;
+ std::array<bptr<A>, size> array;
+ for (auto n = 0u; n < size; n++)
+ {
+ A_total = 0; A_alive = 0;
+ bptr<A> p0;
+ array[0] = bptr<A>{InPlace, 6};
+ for (auto i = 1u; i < size; i++)
+ array[i] = array[i-1];
+ fm_assert(array[0].use_count() == size);
+ fm_assert(A_total == 1 && A_alive == 1);
+ array[(n + 1) % size].reset();
+ array[(n + 2) % size] = bptr<A>((A*)nullptr);
+ array[(n + 3) % size] = move(p0);
+ array[(n + 4) % size].swap(p0);
+ array[(n + 0) % size] = nullptr;
+ p0 = nullptr;
+ for (auto k = 0u; k < size; k++)
+ {
+ for (auto i = 1u; i < size; i++)
+ array[i-1] = array[(i+k) % size];
+ for (auto i = 1u; i < size; i++)
+ check_empty(array[i]);
+ }
+ fm_assert(A_total == 1);
+ fm_assert(A_alive == 0);
+ fm_assert(array == std::array<bptr<A>, size>{});
+ }
+}
+
+void test7()
+{
+ A_total = 0; A_alive = 0;
+ auto p1 = bptr<A>{InPlace, 7};
+ auto p2 = bptr<A>{};
+ p2 = move(p1);
+ fm_assert(A_total == 1 && A_alive == 1);
+ check_empty(p1);
+ check_nonempty(p2);
+
+ p1.reset();
+ check_empty(p1);
+ check_nonempty(p2);
+
+ p1 = move(p2);
+ fm_assert(A_total == 1 && A_alive == 1);
+ check_nonempty(p1);
+ check_empty(p2);
+
+ p1 = move(p2);
+ check_empty(p1);
+ check_empty(p2);
+ fm_assert(A_total == 1 && A_alive == 0);
+
+ A_total = 0; A_alive = 0;
+}
+
} // namespace
void test_app::test_bptr()
{
test1();
test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
}
} // namespace floormat