From 6ef58754d262776c3b21e000f157e16a31e6524f Mon Sep 17 00:00:00 2001 From: Pagwin Date: Thu, 15 Jan 2026 14:21:46 -0500 Subject: [PATCH] everything compiles, now need to figure out ref counting --- Makefile | 2 +- SharedPtr.hpp | 163 +++++++++++++++++++++++++++++++++++++-------- SharedPtr_test.cpp | 34 +++++----- 3 files changed, 154 insertions(+), 45 deletions(-) diff --git a/Makefile b/Makefile index 00f2c31..20c0640 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,3 @@ CXX=clang++ test: SharedPtr_test.cpp SharedPtr.hpp - $(CXX) SharedPtr_test.cpp -o test + $(CXX) SharedPtr_test.cpp -Wall -fsanitize=address -g -o test diff --git a/SharedPtr.hpp b/SharedPtr.hpp index abf9cd2..92f4872 100644 --- a/SharedPtr.hpp +++ b/SharedPtr.hpp @@ -9,51 +9,160 @@ namespace cs440 { using counter = std::atomic; -template class SharedPtr { +class Control { counter count; - (???) underlying; + + virtual void destroy() = 0; public: + Control() : count{1} {}; + void decrement() { + count--; + if (count == 0) { + this->destroy(); + } + } + void increment() { count++; } + virtual ~Control() = default; +}; +template class ControlImpl : public Control { + T *val; + void destroy() override { + delete val; + delete this; + } + +public: + ControlImpl(T *v) : Control{}, val{v} {} + ~ControlImpl() = default; +}; +template class SharedPtr { + T *raw; + Control *underlying; + +public: + template friend class SharedPtr; // typename U meaning a type which inherits from T - SharedPtr(); + SharedPtr() : raw{nullptr}, underlying{nullptr} {} - template explicit SharedPtr(U *); + template explicit SharedPtr(U *p) { + this->raw = p; + this->underlying = new ControlImpl(p); + } - SharedPtr(const SharedPtr &p); - template SharedPtr(const SharedPtr &p); + SharedPtr(const SharedPtr &p) : raw{p.raw}, underlying{p.underlying} { + this->underlying->increment(); + } + template + SharedPtr(const SharedPtr &p) : raw{p.raw}, underlying{p.underlying} { + this->underlying->increment(); + } - SharedPtr(SharedPtr &&p); - template SharedPtr(SharedPtr &&p); + SharedPtr(SharedPtr &&p) : raw{p.raw}, underlying{p.underlying} { + p.raw = nullptr; + p.underlying = nullptr; + }; + template + SharedPtr(SharedPtr &&p) : raw{p.raw}, underlying{p.underlying} { + p.raw = nullptr; + p.underlying = nullptr; + } // needs to handle self assignment - SharedPtr &operator=(const SharedPtr &); - template SharedPtr &operator=(const SharedPtr &); + SharedPtr &operator=(const SharedPtr &rhs) { + if (this->underlying == rhs.underlying) { + return *this; + } + this->raw = rhs.raw; + this->underlying->decrement(); + this->underlying = rhs.underlying; + this->underlying->increment(); + return *this; + } + template SharedPtr &operator=(const SharedPtr &rhs) { + if (this->underlying == rhs.underlying) { + return *this; + } + this->raw = rhs.raw; + this->underlying->decrement(); + this->underlying = rhs.underlying; + this->underlying->increment(); + return *this; + } - SharedPtr &operator=(SharedPtr &&p); - template SharedPtr &operator=(SharedPtr &&p); - ~SharedPtr(); + SharedPtr &operator=(SharedPtr &&rhs) { + if (this == &rhs) { + return *this; + } + this->raw = rhs.raw; + this->underlying->decrement(); + this->underlying = rhs.underlying; + rhs.raw = nullptr; + rhs.underlying = nullptr; + } + template SharedPtr &operator=(SharedPtr &&rhs) { + if (this == &rhs) { + return *this; + } + this->raw = rhs.raw; + this->underlying->decrement(); + this->underlying = rhs.underlying; + rhs.raw = nullptr; + rhs.underlying = nullptr; + } + ~SharedPtr() { this->underlying->decrement(); } void reset() { - this->count = 0; + this->raw = nullptr; + if (this->underlying != nullptr) { + this->underlying->decrement(); + } this->underlying = nullptr; } - template void reset(U *p); - T *get() const; + template void reset(U *p) { + this->raw = p; + if (this->underlying != nullptr) { + this->underlying->decrement(); + } + this->underlying = new ControlImpl(p); + } + T *get() const { return this->raw; } T &operator*() const { return *this->get(); } T *operator->() const { return this->get(); } - explicit operator bool() const; - template - friend bool operator==(const SharedPtr &, const SharedPtr &); - friend bool operator==(const SharedPtr &, std::nullptr_t); - friend bool operator==(std::nullptr_t, const SharedPtr &); - template - friend bool operator!=(const SharedPtr &, const SharedPtr &); - friend bool operator!=(const SharedPtr &, std::nullptr_t); - friend bool operator!=(std::nullptr_t, const SharedPtr &); + explicit operator bool() const { return this->raw; } template - friend SharedPtr static_pointer_cast(const SharedPtr &sp); + friend bool operator==(const SharedPtr &lhs, const SharedPtr &rhs) { + return lhs.raw == rhs.raw; + } + friend bool operator==(const SharedPtr &lhs, std::nullptr_t) { + return lhs.raw == nullptr; + } + friend bool operator==(std::nullptr_t, const SharedPtr &rhs) { + return nullptr == rhs.raw; + } + // template + // friend bool operator!=(const SharedPtr &lhs, const SharedPtr &rhs) + // { + // return lhs.raw != rhs.raw; + // } + // friend bool operator!=(const SharedPtr &lhs, std::nullptr_t) { + // return lhs.raw != nullptr; + // } + // friend bool operator!=(std::nullptr_t, const SharedPtr &rhs) { + // return nullptr != rhs.raw; + // } template - friend SharedPtr dynamic_pointer_cast(const SharedPtr &sp); + friend SharedPtr static_pointer_cast(const SharedPtr &sp) { + SharedPtr ret{}; + ret.raw = static_cast(sp.raw); + ret.underlying = sp.underlying; + } + template + friend SharedPtr dynamic_pointer_cast(const SharedPtr &sp) { + SharedPtr ret{}; + ret.raw = dynamic_cast(sp.raw); + ret.underlying = sp.underlying; + } }; } // namespace cs440 #endif diff --git a/SharedPtr_test.cpp b/SharedPtr_test.cpp index b909f9d..ae11f5a 100644 --- a/SharedPtr_test.cpp +++ b/SharedPtr_test.cpp @@ -264,9 +264,9 @@ void basic_tests_1() { { SharedPtr sp(new Derived); // Test template copy constructor. - // SharedPtr sp3(sp); - // sp2 = sp; - // sp2 = sp2; + SharedPtr sp3(sp); + sp2 = sp; + sp2 = sp2; } } } @@ -279,7 +279,7 @@ void basic_tests_1() { } { SharedPtr sp(new Derived); - // SharedPtr sp2(sp); + SharedPtr sp2(sp); } } @@ -294,9 +294,9 @@ void basic_tests_1() { { SharedPtr sp(new Derived); SharedPtr sp2; - // sp2 = sp; + sp2 = sp; sp2 = sp2; // Self assignment. - // sp2 = sp; + sp2 = sp; sp = sp; } } @@ -306,7 +306,7 @@ void basic_tests_1() { { SharedPtr sp(new Derived); SharedPtr sp2; - // sp2 = sp; + sp2 = sp; sp2 = sp2; sp.reset(); sp.reset(new Derived); @@ -339,10 +339,10 @@ void basic_tests_1() { SharedPtr sp(new Derived); (*sp).value = 1234; - // SharedPtr sp2(sp); - // int i = (*sp2).value; - // assert(i == 1234); - // (*sp2).value = 567; // Should give a syntax error if uncommented. + SharedPtr sp2(sp); + int i = (*sp2).value; + assert(i == 1234); + //(*sp2).value = 567; // Should give a syntax error if uncommented. } // Test ->. @@ -350,9 +350,9 @@ void basic_tests_1() { SharedPtr sp(new Derived); sp->value = 1234; - // SharedPtr sp2(sp); - // int i = sp2->value; - // assert(i == 1234); + SharedPtr sp2(sp); + int i = sp2->value; + assert(i == 1234); // sp2->value = 567; // Should give a syntax error if uncommented. } @@ -361,9 +361,9 @@ void basic_tests_1() { SharedPtr sp(new Derived); sp.get()->value = 1234; - // SharedPtr sp2(sp); - // int i = sp2.get()->value; - // assert(i == 1234); + SharedPtr sp2(sp); + int i = sp2.get()->value; + assert(i == 1234); } // Test bool.