examples

Toy examples in single C files.
git clone git://henryandlizzy.uk/examples
Log | Files | Refs

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:
M.gitignore | 1+
Asrc/owning_ptr.cpp | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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(); +}