commit 82f4a9b73624009ce791477574d386377c74c9b4
parent e745bc260c0b094e692e4dc198797e87fa9d33f6
Author: Henry Wilson <henry@henryandlizzy.uk>
Date: Mon, 6 Feb 2023 22:00:10 +0000
owning_ptr: Add experiment in avoiding shared_ptr liveleaks
Diffstat:
2 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -33,6 +33,7 @@
/model
/morse
/mutex_container
+/owning_ptr
/pulse-async-client
/pulse-simple-client
/regex
diff --git a/src/owning_ptr.cpp b/src/owning_ptr.cpp
@@ -0,0 +1,82 @@
+#include <memory>
+#include <cassert>
+#include <iostream>
+#include <set>
+
+using namespace std;
+
+template <typename T>
+struct owning_ptr : shared_ptr<T>
+{
+ owning_ptr() = default;
+ explicit owning_ptr(shared_ptr<T> p)
+ : shared_ptr<T>(move(p))
+ {
+ assert(this->use_count() <= 1);
+ }
+ ~owning_ptr()
+ {
+ if (*this)
+ (*this)->pre_destroy();
+ if (auto n = this->use_count(); n > 1)
+ {
+ cerr << "owning_ptr not outliving " << n - 1 << " references\n";
+ terminate();
+ }
+ }
+ owning_ptr(owning_ptr const&) = delete;
+ owning_ptr& operator =(owning_ptr const&) = delete;
+ owning_ptr(owning_ptr&&) = default;
+ owning_ptr& operator =(owning_ptr&&) = default;
+};
+
+struct node : enable_shared_from_this<node>
+{
+ set<shared_ptr<node>> others = {};
+
+ void pre_destroy()
+ {
+ for (auto& o : others)
+ o->others.erase(shared_from_this());
+ }
+
+ [[nodiscard]] static owning_ptr<node> construct()
+ {
+ return owning_ptr{shared_ptr<node>{new node{}}};
+ }
+
+ ~node()
+ {
+ cout << "~node(): " << others.size() << endl;
+ }
+
+private:
+ node() = default;
+};
+
+void join(node& a, node& b)
+{
+ a.others.insert(b.shared_from_this());
+ b.others.insert(a.shared_from_this());
+}
+
+set<owning_ptr<node>> nodes;
+
+int main()
+{
+ nodes.insert(node::construct());
+ auto p1 = node::construct();
+ auto q1 = node::construct();
+ auto r1 = node::construct();
+ join(*p1, *q1);
+ join(*p1, *r1);
+ join(*q1, *r1);
+
+ join(*p1, *p1);
+
+ shared_ptr<node> p2 = p1;
+ weak_ptr<node> p3 = p1;
+
+ owning_ptr<node> p4 = move(p1);
+ p2.reset();
+}