Require explicit copies for Ref/WeakRef

This commit is contained in:
2025-09-12 11:59:56 -04:00
parent 674ff581e7
commit f89868058a
4 changed files with 145 additions and 162 deletions

View File

@@ -27,6 +27,18 @@ template <typename T> struct PointerTraits<std::shared_ptr<T>> {
return std::make_shared<T>(std::forward<Args>(args)...);
}
static pointer_type copy(const pointer_type &ptr) {
return ptr; // std::shared_ptr copies implicitly
}
static weak_type as_weak(const pointer_type &ptr) {
return ptr; // std::weak_ptr converts implicitly from std::shared_ptr
}
static weak_type copy_weak(const weak_type &weak) {
return weak; // std::weak_ptr copies implicitly
}
static const char *name() { return "std::shared_ptr"; }
static const char *weak_name() { return "std::weak_ptr"; }
};
@@ -39,6 +51,18 @@ template <typename T> struct PointerTraits<Ref<T>> {
return make_ref<T>(std::forward<Args>(args)...);
}
static pointer_type copy(const pointer_type &ptr) {
return ptr.copy(); // Ref requires explicit copy
}
static weak_type as_weak(const pointer_type &ptr) {
return ptr.as_weak(); // Ref requires explicit as_weak
}
static weak_type copy_weak(const weak_type &weak) {
return weak.copy(); // WeakRef requires explicit copy
}
static const char *name() { return "Ref"; }
static const char *weak_name() { return "WeakRef"; }
};
@@ -67,7 +91,7 @@ void benchmark_copy(ankerl::nanobench::Bench &bench) {
auto original = Traits::make(TestObject{123});
bench.run(std::string(Traits::name()) + " copy", [&] {
auto copy = original;
auto copy = Traits::copy(original);
ankerl::nanobench::doNotOptimizeAway(copy);
});
}
@@ -91,9 +115,9 @@ void benchmark_weak_copy(ankerl::nanobench::Bench &bench) {
force_multithreaded();
auto strong_ptr = Traits::make(TestObject{123});
typename Traits::weak_type weak_original = strong_ptr;
typename Traits::weak_type weak_original = Traits::as_weak(strong_ptr);
bench.run(std::string(Traits::weak_name()) + " copy", [&] {
auto weak_copy = weak_original;
auto weak_copy = Traits::copy_weak(weak_original);
ankerl::nanobench::doNotOptimizeAway(weak_copy);
});
}
@@ -103,7 +127,7 @@ void benchmark_weak_move(ankerl::nanobench::Bench &bench) {
using Traits = PointerTraits<PtrType>;
auto strong_ptr = Traits::make(TestObject{123});
typename Traits::weak_type weak_original = strong_ptr;
typename Traits::weak_type weak_original = Traits::as_weak(strong_ptr);
bench.run(std::string(Traits::weak_name()) + " move", [&] {
auto weak_moved = std::move(weak_original);
ankerl::nanobench::doNotOptimizeAway(weak_moved);
@@ -126,7 +150,7 @@ void benchmark_weak_lock_success(ankerl::nanobench::Bench &bench) {
using Traits = PointerTraits<PtrType>;
auto strong_ptr = Traits::make(TestObject{789});
typename Traits::weak_type weak_ptr = strong_ptr;
typename Traits::weak_type weak_ptr = Traits::as_weak(strong_ptr);
bench.run(std::string(Traits::weak_name()) + " lock success", [&] {
auto locked = weak_ptr.lock();
ankerl::nanobench::doNotOptimizeAway(locked);
@@ -140,7 +164,7 @@ void benchmark_weak_lock_failure(ankerl::nanobench::Bench &bench) {
typename Traits::weak_type weak_ptr;
{
auto strong_ptr = Traits::make(TestObject{999});
weak_ptr = strong_ptr;
weak_ptr = Traits::as_weak(strong_ptr);
}
bench.run(std::string(Traits::weak_name()) + " lock failure", [&] {
auto locked = weak_ptr.lock();
@@ -163,7 +187,7 @@ void benchmark_multithreaded_copy(ankerl::nanobench::Bench &bench,
for (int i = 0; i < num_threads - 1; ++i) {
background_threads.emplace_back([&]() {
while (keep_running.load(std::memory_order_relaxed)) {
auto copy = ptr;
auto copy = Traits::copy(ptr);
ankerl::nanobench::doNotOptimizeAway(copy);
}
});
@@ -171,7 +195,7 @@ void benchmark_multithreaded_copy(ankerl::nanobench::Bench &bench,
// Benchmark the foreground thread under contention
bench.run(std::string(Traits::name()) + " copy under contention", [&] {
auto copy = ptr;
auto copy = Traits::copy(ptr);
ankerl::nanobench::doNotOptimizeAway(copy);
});
@@ -189,7 +213,7 @@ void benchmark_multithreaded_weak_lock(ankerl::nanobench::Bench &bench,
// Create the shared object and weak reference outside the benchmark
auto strong_ptr = Traits::make(TestObject{789});
typename Traits::weak_type weak_ptr = strong_ptr;
typename Traits::weak_type weak_ptr = Traits::as_weak(strong_ptr);
// Create background threads that will create contention
std::atomic<bool> keep_running{true};
@@ -224,7 +248,7 @@ void benchmark_weak_copy_with_strong_contention(ankerl::nanobench::Bench &bench,
// Create the shared object and weak reference outside the benchmark
auto strong_ptr = Traits::make(TestObject{456});
typename Traits::weak_type weak_ptr = strong_ptr;
typename Traits::weak_type weak_ptr = Traits::as_weak(strong_ptr);
// Create background threads copying the strong pointer
std::atomic<bool> keep_running{true};
@@ -233,7 +257,7 @@ void benchmark_weak_copy_with_strong_contention(ankerl::nanobench::Bench &bench,
for (int i = 0; i < num_threads - 1; ++i) {
background_threads.emplace_back([&]() {
while (keep_running.load(std::memory_order_relaxed)) {
auto copy = strong_ptr;
auto copy = Traits::copy(strong_ptr);
ankerl::nanobench::doNotOptimizeAway(copy);
}
});
@@ -242,7 +266,7 @@ void benchmark_weak_copy_with_strong_contention(ankerl::nanobench::Bench &bench,
// Benchmark weak reference copying under strong reference contention
bench.run(std::string(Traits::weak_name()) + " copy with strong contention",
[&] {
auto weak_copy = weak_ptr;
auto weak_copy = Traits::copy_weak(weak_ptr);
ankerl::nanobench::doNotOptimizeAway(weak_copy);
});
@@ -260,7 +284,7 @@ void benchmark_strong_copy_with_weak_contention(ankerl::nanobench::Bench &bench,
// Create the shared object and weak reference outside the benchmark
auto strong_ptr = Traits::make(TestObject{789});
typename Traits::weak_type weak_ptr = strong_ptr;
typename Traits::weak_type weak_ptr = Traits::as_weak(strong_ptr);
// Create background threads copying the weak pointer
std::atomic<bool> keep_running{true};
@@ -269,7 +293,7 @@ void benchmark_strong_copy_with_weak_contention(ankerl::nanobench::Bench &bench,
for (int i = 0; i < num_threads - 1; ++i) {
background_threads.emplace_back([&]() {
while (keep_running.load(std::memory_order_relaxed)) {
auto weak_copy = weak_ptr;
auto weak_copy = Traits::copy_weak(weak_ptr);
ankerl::nanobench::doNotOptimizeAway(weak_copy);
}
});
@@ -277,7 +301,7 @@ void benchmark_strong_copy_with_weak_contention(ankerl::nanobench::Bench &bench,
// Benchmark strong reference copying under weak reference contention
bench.run(std::string(Traits::name()) + " copy with weak contention", [&] {
auto strong_copy = strong_ptr;
auto strong_copy = Traits::copy(strong_ptr);
ankerl::nanobench::doNotOptimizeAway(strong_copy);
});