From b3b8a79f7d4699744b31c423494c4872cafa8371 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 19 Sep 2024 23:10:34 +0200 Subject: [PATCH 01/15] Added shared_ptr with ControlBlock (responsible for shared and weak counts) and with constructor, destructor --- homework/shared_ptr.hpp | 45 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 homework/shared_ptr.hpp diff --git a/homework/shared_ptr.hpp b/homework/shared_ptr.hpp new file mode 100644 index 00000000..f19baf1f --- /dev/null +++ b/homework/shared_ptr.hpp @@ -0,0 +1,45 @@ +#pragma once +#include + +namespace my { + +template +class shared_ptr { +private: + T* ptr; + + struct ControlBlock { + std::atomic shared_count; + std::atomic weak_count; + void (*deleter)(T*); + + ControlBlock() + : shared_count(1), weak_count(0), deleter(nullptr) {} + }; + ControlBlock* control_block; + +public: + explicit shared_ptr(T* p = nullptr) : ptr(p), control_block(new ControlBlock()){} + + ~shared_ptr() { + if (control_block) + { + if (--control_block->shared_count == 0) + { + if (ptr && control_block->deleter) + { + control_block->deleter(ptr); + }else{ + delete ptr; + } + if (control_block->weak_count == 0) + { + delete control_block; + } + } + } + } + + +}; +} // namespace my \ No newline at end of file From 5c8dbb7b1b9031bfd6acfec0c08f3db800e8e1b8 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:23:08 +0200 Subject: [PATCH 02/15] -First version with CmakeLists, 2 tests and basic implementation of shared_ptr --- homework/CMakeLists.txt | 27 ++++++++++++++++ homework/shared_ptr.hpp | 59 ++++++++++++++++++++++++++++------- homework/shared_ptr_tests.cpp | 18 +++++++++++ 3 files changed, 93 insertions(+), 11 deletions(-) create mode 100644 homework/CMakeLists.txt create mode 100644 homework/shared_ptr_tests.cpp diff --git a/homework/CMakeLists.txt b/homework/CMakeLists.txt new file mode 100644 index 00000000..3b6c3ee6 --- /dev/null +++ b/homework/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.10) +project(SharedPtrProject) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +#include of shared_ptr.hpp +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +#GTest include +include(FetchContent) +FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG release-1.12.1 +) +FetchContent_MakeAvailable(googletest) + +#Test executable +add_executable(shared_ptr_tests shared_ptr_tests.cpp) + +#Link GTest +target_link_libraries(shared_ptr_tests gtest gtest_main) + +enable_testing() + +add_test(NAME SharedPtrTests COMMAND shared_ptr_tests) \ No newline at end of file diff --git a/homework/shared_ptr.hpp b/homework/shared_ptr.hpp index f19baf1f..bd1607b5 100644 --- a/homework/shared_ptr.hpp +++ b/homework/shared_ptr.hpp @@ -19,27 +19,64 @@ class shared_ptr { ControlBlock* control_block; public: - explicit shared_ptr(T* p = nullptr) : ptr(p), control_block(new ControlBlock()){} + explicit shared_ptr(T* p = nullptr) + : ptr(p), control_block(new ControlBlock()) {} + + shared_ptr(const shared_ptr& other) + : ptr(other.ptr), control_block(other.control_block) { + if (control_block) { + ++control_block->shared_count; + } + } + + shared_ptr& operator=(const shared_ptr& otherSharedPtr) { + shared_ptr(otherSharedPtr).swap(*this); + return *this; + } + + shared_ptr(shared_ptr&& otherSharedPtr) noexcept + : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { + otherSharedPtr.ptr = nullptr; + otherSharedPtr.control_block = nullptr; + } + + shared_ptr& operator=(shared_ptr&& otherSharedPtr) noexcept { + shared_ptr(std::move(otherSharedPtr)).swap(*this); + return *this; + } ~shared_ptr() { - if (control_block) - { - if (--control_block->shared_count == 0) - { - if (ptr && control_block->deleter) - { + if (control_block) { + if (--control_block->shared_count == 0) { + if (ptr && control_block->deleter) { control_block->deleter(ptr); - }else{ + } else { delete ptr; } - if (control_block->weak_count == 0) - { + if (control_block->weak_count == 0) { delete control_block; - } + } } } } + T& operator*() const { return *ptr; } + T* operator->() const { return ptr; } + T* get() const { return ptr; } + + size_t use_count() const { + return (control_block ? control_block->shared_count.load() : 0); + } + + explicit operator bool() const { return ptr != nullptr; } + + void swap(shared_ptr& otherSharedPtr) noexcept { + std::swap(ptr, otherSharedPtr.ptr); + std::swap(control_block, otherSharedPtr.control_block); + } + void reset(T* p = nullptr) { + shared_ptr(p).swap(*this); + } }; } // namespace my \ No newline at end of file diff --git a/homework/shared_ptr_tests.cpp b/homework/shared_ptr_tests.cpp new file mode 100644 index 00000000..03f92695 --- /dev/null +++ b/homework/shared_ptr_tests.cpp @@ -0,0 +1,18 @@ +#include +#include "shared_ptr.hpp" + +// Instantiate the template class for testing +template class my::shared_ptr; + +TEST(SharedPtrTest, DefaultConstructor) { + my::shared_ptr sp; + EXPECT_EQ(sp.use_count(), 1); + EXPECT_FALSE(sp); +} + +TEST(SharedPtrTest, ConstructorWithPointer) { + my::shared_ptr sp(new int(42)); + EXPECT_EQ(sp.use_count(), 1); + EXPECT_TRUE(sp); + EXPECT_EQ(*sp, 42); +} \ No newline at end of file From ea42a52fe107c7bfbcee979b4f0c9583c48d25b0 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:34:47 +0200 Subject: [PATCH 03/15] test msg - build issues? --- homework/shared_ptr.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homework/shared_ptr.hpp b/homework/shared_ptr.hpp index bd1607b5..a731fdb5 100644 --- a/homework/shared_ptr.hpp +++ b/homework/shared_ptr.hpp @@ -1,6 +1,8 @@ #pragma once #include +//test + namespace my { template From 5d48ba8f463629fd44c1ec6f7b92fe0cd400fe70 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:36:36 +0200 Subject: [PATCH 04/15] test --- homework/shared_ptr.hpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/homework/shared_ptr.hpp b/homework/shared_ptr.hpp index a731fdb5..7fd0a8ad 100644 --- a/homework/shared_ptr.hpp +++ b/homework/shared_ptr.hpp @@ -31,16 +31,16 @@ class shared_ptr { } } - shared_ptr& operator=(const shared_ptr& otherSharedPtr) { - shared_ptr(otherSharedPtr).swap(*this); - return *this; - } - - shared_ptr(shared_ptr&& otherSharedPtr) noexcept - : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { - otherSharedPtr.ptr = nullptr; - otherSharedPtr.control_block = nullptr; - } + // shared_ptr& operator=(const shared_ptr& otherSharedPtr) { + // shared_ptr(otherSharedPtr).swap(*this); + // return *this; + // } + + // shared_ptr(shared_ptr&& otherSharedPtr) noexcept + // : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { + // otherSharedPtr.ptr = nullptr; + // otherSharedPtr.control_block = nullptr; + // } shared_ptr& operator=(shared_ptr&& otherSharedPtr) noexcept { shared_ptr(std::move(otherSharedPtr)).swap(*this); From bc45865eb5626c4698575d8d0814a73a1f65ab51 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:41:43 +0200 Subject: [PATCH 05/15] Folders changed to run build properly --- homework/{ => shared_ptr}/shared_ptr.hpp | 20 +++++++++----------- homework/{ => tests}/shared_ptr_tests.cpp | 0 2 files changed, 9 insertions(+), 11 deletions(-) rename homework/{ => shared_ptr}/shared_ptr.hpp (81%) rename homework/{ => tests}/shared_ptr_tests.cpp (100%) diff --git a/homework/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp similarity index 81% rename from homework/shared_ptr.hpp rename to homework/shared_ptr/shared_ptr.hpp index 7fd0a8ad..bd1607b5 100644 --- a/homework/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -1,8 +1,6 @@ #pragma once #include -//test - namespace my { template @@ -31,16 +29,16 @@ class shared_ptr { } } - // shared_ptr& operator=(const shared_ptr& otherSharedPtr) { - // shared_ptr(otherSharedPtr).swap(*this); - // return *this; - // } + shared_ptr& operator=(const shared_ptr& otherSharedPtr) { + shared_ptr(otherSharedPtr).swap(*this); + return *this; + } - // shared_ptr(shared_ptr&& otherSharedPtr) noexcept - // : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { - // otherSharedPtr.ptr = nullptr; - // otherSharedPtr.control_block = nullptr; - // } + shared_ptr(shared_ptr&& otherSharedPtr) noexcept + : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { + otherSharedPtr.ptr = nullptr; + otherSharedPtr.control_block = nullptr; + } shared_ptr& operator=(shared_ptr&& otherSharedPtr) noexcept { shared_ptr(std::move(otherSharedPtr)).swap(*this); diff --git a/homework/shared_ptr_tests.cpp b/homework/tests/shared_ptr_tests.cpp similarity index 100% rename from homework/shared_ptr_tests.cpp rename to homework/tests/shared_ptr_tests.cpp From f49003975ecce4d0b31e0e51f6ac18b757513bf4 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:49:40 +0200 Subject: [PATCH 06/15] Changed folder, for tests --- homework/{tests => shared_ptr}/shared_ptr_tests.cpp | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename homework/{tests => shared_ptr}/shared_ptr_tests.cpp (100%) diff --git a/homework/tests/shared_ptr_tests.cpp b/homework/shared_ptr/shared_ptr_tests.cpp similarity index 100% rename from homework/tests/shared_ptr_tests.cpp rename to homework/shared_ptr/shared_ptr_tests.cpp From b14c283108e5562584211963ab0d8945287677f6 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Thu, 26 Sep 2024 23:58:06 +0200 Subject: [PATCH 07/15] Update for shared_ptr and tests --- homework/CMakeLists.txt | 4 +- homework/shared_ptr/shared_ptr.hpp | 17 +++++++- homework/shared_ptr/shared_ptr_tests.cpp | 50 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 3 deletions(-) diff --git a/homework/CMakeLists.txt b/homework/CMakeLists.txt index 3b6c3ee6..a1d7acaa 100644 --- a/homework/CMakeLists.txt +++ b/homework/CMakeLists.txt @@ -5,7 +5,7 @@ set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) #include of shared_ptr.hpp -include_directories(${CMAKE_CURRENT_SOURCE_DIR}) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr) #GTest include include(FetchContent) @@ -17,7 +17,7 @@ FetchContent_Declare( FetchContent_MakeAvailable(googletest) #Test executable -add_executable(shared_ptr_tests shared_ptr_tests.cpp) +add_executable(shared_ptr_tests shared_ptr/shared_ptr_tests.cpp) #Link GTest target_link_libraries(shared_ptr_tests gtest gtest_main) diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index bd1607b5..51070edd 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -76,7 +76,22 @@ class shared_ptr { } void reset(T* p = nullptr) { - shared_ptr(p).swap(*this); + if (p != ptr) { + if (control_block) { + if (--control_block->shared_count == 0) { + delete ptr; + if (control_block->weak_count == 0) { + delete control_block; + } + } + } + ptr = p; + if (p) { + control_block = new ControlBlock(); + } else { + control_block = nullptr; + } } +} }; } // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/shared_ptr_tests.cpp b/homework/shared_ptr/shared_ptr_tests.cpp index 03f92695..cd6bd6eb 100644 --- a/homework/shared_ptr/shared_ptr_tests.cpp +++ b/homework/shared_ptr/shared_ptr_tests.cpp @@ -15,4 +15,54 @@ TEST(SharedPtrTest, ConstructorWithPointer) { EXPECT_EQ(sp.use_count(), 1); EXPECT_TRUE(sp); EXPECT_EQ(*sp, 42); +} + +TEST(SharedPtrTest, ArrowOperator) { + struct TestStruct { + int value; + TestStruct(int v) : value(v) {} + }; + + my::shared_ptr sp(new TestStruct(42)); + EXPECT_EQ(sp->value, 42); + sp->value = 24; + EXPECT_EQ(sp->value, 24); +} + +TEST(SharedPtrTest, GetMethod) { + int* raw_ptr = new int(10); + my::shared_ptr sp(raw_ptr); + + EXPECT_EQ(sp.get(), raw_ptr); + EXPECT_EQ(*sp.get(), 10); + + EXPECT_EQ(sp.use_count(), 1); +} + +TEST(SharedPtrTest, ResetMethod) { + my::shared_ptr sp(new int(5)); + EXPECT_EQ(*sp, 5); + EXPECT_EQ(sp.use_count(), 1); + + sp.reset(new int(10)); + EXPECT_EQ(*sp, 10); + EXPECT_EQ(sp.use_count(), 1); + + sp.reset(); + EXPECT_EQ(sp.get(), nullptr); + EXPECT_EQ(sp.use_count(), 0); +} + +TEST(SharedPtrTest, ResetWithMultipleReferences) { + my::shared_ptr sp1(new int(5)); + my::shared_ptr sp2 = sp1; + + EXPECT_EQ(sp1.use_count(), 2); + EXPECT_EQ(sp2.use_count(), 2); + + sp1.reset(new int(10)); + EXPECT_EQ(*sp1, 10); + EXPECT_EQ(sp1.use_count(), 1); + EXPECT_EQ(*sp2, 5); + EXPECT_EQ(sp2.use_count(), 1); } \ No newline at end of file From bea8d74a12c515f44652144fc5b5b650fc030787 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Fri, 27 Sep 2024 00:02:47 +0200 Subject: [PATCH 08/15] More tests and formatting --- homework/shared_ptr/shared_ptr.hpp | 26 ++++----- homework/shared_ptr/shared_ptr_tests.cpp | 69 ++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 16 deletions(-) diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 51070edd..080fde6a 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -76,22 +76,22 @@ class shared_ptr { } void reset(T* p = nullptr) { - if (p != ptr) { - if (control_block) { - if (--control_block->shared_count == 0) { - delete ptr; - if (control_block->weak_count == 0) { - delete control_block; + if (p != ptr) { + if (control_block) { + if (--control_block->shared_count == 0) { + delete ptr; + if (control_block->weak_count == 0) { + delete control_block; + } } } - } - ptr = p; - if (p) { - control_block = new ControlBlock(); - } else { - control_block = nullptr; + ptr = p; + if (p) { + control_block = new ControlBlock(); + } else { + control_block = nullptr; + } } } -} }; } // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/shared_ptr_tests.cpp b/homework/shared_ptr/shared_ptr_tests.cpp index cd6bd6eb..f6e6f26e 100644 --- a/homework/shared_ptr/shared_ptr_tests.cpp +++ b/homework/shared_ptr/shared_ptr_tests.cpp @@ -20,7 +20,8 @@ TEST(SharedPtrTest, ConstructorWithPointer) { TEST(SharedPtrTest, ArrowOperator) { struct TestStruct { int value; - TestStruct(int v) : value(v) {} + TestStruct(int v) + : value(v) {} }; my::shared_ptr sp(new TestStruct(42)); @@ -32,7 +33,7 @@ TEST(SharedPtrTest, ArrowOperator) { TEST(SharedPtrTest, GetMethod) { int* raw_ptr = new int(10); my::shared_ptr sp(raw_ptr); - + EXPECT_EQ(sp.get(), raw_ptr); EXPECT_EQ(*sp.get(), 10); @@ -56,7 +57,7 @@ TEST(SharedPtrTest, ResetMethod) { TEST(SharedPtrTest, ResetWithMultipleReferences) { my::shared_ptr sp1(new int(5)); my::shared_ptr sp2 = sp1; - + EXPECT_EQ(sp1.use_count(), 2); EXPECT_EQ(sp2.use_count(), 2); @@ -65,4 +66,66 @@ TEST(SharedPtrTest, ResetWithMultipleReferences) { EXPECT_EQ(sp1.use_count(), 1); EXPECT_EQ(*sp2, 5); EXPECT_EQ(sp2.use_count(), 1); +} +TEST(SharedPtrTest, CopyConstructor) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2(sp1); + EXPECT_EQ(*sp1, 42); + EXPECT_EQ(*sp2, 42); + EXPECT_EQ(sp1.use_count(), 2); + EXPECT_EQ(sp2.use_count(), 2); +} + +TEST(SharedPtrTest, CopyAssignment) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2; + sp2 = sp1; + EXPECT_EQ(*sp1, 42); + EXPECT_EQ(*sp2, 42); + EXPECT_EQ(sp1.use_count(), 2); + EXPECT_EQ(sp2.use_count(), 2); +} + +TEST(SharedPtrTest, MoveConstructor) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2(std::move(sp1)); + EXPECT_EQ(*sp2, 42); + EXPECT_EQ(sp2.use_count(), 1); + EXPECT_FALSE(sp1); +} + +TEST(SharedPtrTest, MoveAssignment) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2; + sp2 = std::move(sp1); + EXPECT_EQ(*sp2, 42); + EXPECT_EQ(sp2.use_count(), 1); + EXPECT_FALSE(sp1); +} + +TEST(SharedPtrTest, BoolOperator) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2; + EXPECT_TRUE(sp1); + EXPECT_FALSE(sp2); +} + +TEST(SharedPtrTest, Swap) { + my::shared_ptr sp1(new int(42)); + my::shared_ptr sp2(new int(24)); + sp1.swap(sp2); + EXPECT_EQ(*sp1, 24); + EXPECT_EQ(*sp2, 42); +} + +TEST(SharedPtrTest, MultipleSharedPtrs) { + my::shared_ptr sp1(new int(42)); + { + my::shared_ptr sp2 = sp1; + my::shared_ptr sp3 = sp1; + EXPECT_EQ(sp1.use_count(), 3); + EXPECT_EQ(sp2.use_count(), 3); + EXPECT_EQ(sp3.use_count(), 3); + } + EXPECT_EQ(sp1.use_count(), 1); } \ No newline at end of file From 765d90d37e9ca3ba3e0eca6e1e8f5090c4ba1d46 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Sat, 11 Jan 2025 12:51:49 +0100 Subject: [PATCH 09/15] -Required changes in shared_ptr and weak_ptr implementation. -Changes in CMakeLists --- homework/CMakeLists.txt | 16 ++-- homework/shared_ptr/shared_ptr.hpp | 120 +++++++++++++------------ homework/shared_ptr/weak_ptr.hpp | 102 +++++++++++++++++++++ homework/shared_ptr/weak_ptr_tests.cpp | 48 ++++++++++ 4 files changed, 224 insertions(+), 62 deletions(-) create mode 100644 homework/shared_ptr/weak_ptr.hpp create mode 100644 homework/shared_ptr/weak_ptr_tests.cpp diff --git a/homework/CMakeLists.txt b/homework/CMakeLists.txt index a1d7acaa..ce6c61f1 100644 --- a/homework/CMakeLists.txt +++ b/homework/CMakeLists.txt @@ -1,11 +1,14 @@ cmake_minimum_required(VERSION 3.10) project(SharedPtrProject) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) -#include of shared_ptr.hpp -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/shared_ptr) +#compile options +add_compile_options(-Wall -Wextra -Werror -pedantic) + +#include header files +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) #GTest include include(FetchContent) @@ -18,10 +21,13 @@ FetchContent_MakeAvailable(googletest) #Test executable add_executable(shared_ptr_tests shared_ptr/shared_ptr_tests.cpp) +add_executable(weak_ptr_tests shared_ptr/weak_ptr_tests.cpp) #Link GTest -target_link_libraries(shared_ptr_tests gtest gtest_main) +target_link_libraries(shared_ptr_tests GTest::gtest GTest::gtest_main) +target_link_libraries(weak_ptr_tests GTest::gtest GTest::gtest_main) enable_testing() -add_test(NAME SharedPtrTests COMMAND shared_ptr_tests) \ No newline at end of file +add_test(NAME SharedPtrTests COMMAND shared_ptr_tests) +add_test(NAME WeakPtrTests COMMAND weak_ptr_tests) \ No newline at end of file diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 080fde6a..52798114 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -1,97 +1,103 @@ #pragma once #include +#include +#include namespace my { +template +class weak_ptr; // Forward declaration + template class shared_ptr { -private: - T* ptr; + friend class weak_ptr; +public: struct ControlBlock { - std::atomic shared_count; - std::atomic weak_count; - void (*deleter)(T*); - - ControlBlock() - : shared_count(1), weak_count(0), deleter(nullptr) {} + std::atomic shared_count; + std::atomic weak_count; + + ControlBlock() : shared_count(1), weak_count(0) {} }; - ControlBlock* control_block; -public: - explicit shared_ptr(T* p = nullptr) + explicit shared_ptr(T* p = nullptr) : ptr(p), control_block(new ControlBlock()) {} - - shared_ptr(const shared_ptr& other) + + shared_ptr(const shared_ptr& other) : ptr(other.ptr), control_block(other.control_block) { if (control_block) { ++control_block->shared_count; } } - shared_ptr& operator=(const shared_ptr& otherSharedPtr) { - shared_ptr(otherSharedPtr).swap(*this); + shared_ptr& operator=(const shared_ptr& other) { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + if (control_block) { + ++control_block->shared_count; + } + } return *this; } - shared_ptr(shared_ptr&& otherSharedPtr) noexcept - : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { - otherSharedPtr.ptr = nullptr; - otherSharedPtr.control_block = nullptr; + shared_ptr(shared_ptr&& other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + other.ptr = nullptr; + other.control_block = nullptr; } - shared_ptr& operator=(shared_ptr&& otherSharedPtr) noexcept { - shared_ptr(std::move(otherSharedPtr)).swap(*this); + shared_ptr& operator=(shared_ptr&& other) noexcept { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + other.ptr = nullptr; + other.control_block = nullptr; + } return *this; } ~shared_ptr() { - if (control_block) { - if (--control_block->shared_count == 0) { - if (ptr && control_block->deleter) { - control_block->deleter(ptr); - } else { - delete ptr; - } - if (control_block->weak_count == 0) { - delete control_block; - } - } - } + reset(); } + void swap(shared_ptr& other) noexcept { + std::swap(ptr, other.ptr); + std::swap(control_block, other.control_block); + } + + T* get() const noexcept { return ptr; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } - T* get() const { return ptr; } - - size_t use_count() const { - return (control_block ? control_block->shared_count.load() : 0); + + std::size_t use_count() const noexcept { + return control_block ? control_block->shared_count.load() : 0; } - explicit operator bool() const { return ptr != nullptr; } - - void swap(shared_ptr& otherSharedPtr) noexcept { - std::swap(ptr, otherSharedPtr.ptr); - std::swap(control_block, otherSharedPtr.control_block); - } + explicit operator bool() const noexcept { return ptr != nullptr; } void reset(T* p = nullptr) { - if (p != ptr) { - if (control_block) { - if (--control_block->shared_count == 0) { - delete ptr; - if (control_block->weak_count == 0) { - delete control_block; - } + if (control_block) { + if (--control_block->shared_count == 0) { + delete ptr; + if (control_block->weak_count == 0) { + delete control_block; } } - ptr = p; - if (p) { - control_block = new ControlBlock(); - } else { - control_block = nullptr; - } + } + ptr = p; + if (p) { + control_block = new ControlBlock(); + } else { + control_block = nullptr; } } + +private: + T* ptr; + ControlBlock* control_block; }; -} // namespace my \ No newline at end of file + +} // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/weak_ptr.hpp b/homework/shared_ptr/weak_ptr.hpp new file mode 100644 index 00000000..b956a106 --- /dev/null +++ b/homework/shared_ptr/weak_ptr.hpp @@ -0,0 +1,102 @@ +#ifndef WEAK_PTR_HPP +#define WEAK_PTR_HPP + +#include "shared_ptr.hpp" +#include + +namespace my { + +template +class weak_ptr { + friend class shared_ptr; + +public: + weak_ptr() noexcept : ptr(nullptr), control_block(nullptr) {} + + weak_ptr(const shared_ptr& sp) noexcept + : ptr(sp.ptr), control_block(sp.control_block) { + if (control_block) { + control_block->weak_count++; + } + } + + weak_ptr(const weak_ptr& other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + if (control_block) { + control_block->weak_count++; + } + } + + weak_ptr(weak_ptr&& other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + other.ptr = nullptr; + other.control_block = nullptr; + } + + ~weak_ptr() { + reset(); + } + + weak_ptr& operator=(const weak_ptr& other) noexcept { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + if (control_block) { + control_block->weak_count++; + } + } + return *this; + } + + weak_ptr& operator=(weak_ptr&& other) noexcept { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + other.ptr = nullptr; + other.control_block = nullptr; + } + return *this; + } + + void reset() noexcept { + if (control_block) { + control_block->weak_count--; + if (control_block->weak_count == 0 && control_block->shared_count == 0) { + delete control_block; + } + ptr = nullptr; + control_block = nullptr; + } + } + + std::size_t use_count() const noexcept { + return control_block ? control_block->shared_count.load() : 0; + } + + bool expired() const noexcept { + return use_count() == 0; + } + + shared_ptr lock() const noexcept { + if (expired()) { + return shared_ptr(); + } + shared_ptr sp; + sp.ptr = ptr; + sp.control_block = control_block; + if (control_block) { + ++control_block->shared_count; + } + return sp; + } + +private: + T* ptr; + typename shared_ptr::ControlBlock* control_block; +}; + +} // namespace my + +#endif // WEAK_PTR_HPP \ No newline at end of file diff --git a/homework/shared_ptr/weak_ptr_tests.cpp b/homework/shared_ptr/weak_ptr_tests.cpp new file mode 100644 index 00000000..119c44ce --- /dev/null +++ b/homework/shared_ptr/weak_ptr_tests.cpp @@ -0,0 +1,48 @@ +#include "weak_ptr.hpp" +#include + +// Instantiate the template class for testing +template class my::weak_ptr; + +TEST(WeakPtrTest, DefaultConstructor) { + my::weak_ptr wp; + EXPECT_TRUE(wp.expired()); + EXPECT_EQ(wp.use_count(), 0); +} + +TEST(WeakPtrTest, UseCount) { + my::shared_ptr sp(new int(10)); + my::weak_ptr wp(sp); + EXPECT_EQ(wp.use_count(), 1); +} + +TEST(WeakPtrTest, Expired) { + my::shared_ptr sp(new int(20)); + my::weak_ptr wp(sp); + EXPECT_FALSE(wp.expired()); + sp.reset(); + EXPECT_TRUE(wp.expired()); +} + +TEST(WeakPtrTest, Reset) { + my::shared_ptr sp(new int(40)); + my::weak_ptr wp(sp); + wp.reset(); + EXPECT_TRUE(wp.expired()); +} + +TEST(WeakPtrTest, CopyConstructor) { + my::shared_ptr sp(new int(50)); + my::weak_ptr wp1(sp); + my::weak_ptr wp2(wp1); + EXPECT_EQ(wp1.use_count(), 1); + EXPECT_EQ(wp2.use_count(), 1); +} + +TEST(WeakPtrTest, MoveConstructor) { + my::shared_ptr sp(new int(60)); + my::weak_ptr wp1(sp); + my::weak_ptr wp2(std::move(wp1)); + EXPECT_EQ(wp2.use_count(), 1); + EXPECT_TRUE(wp1.expired()); +} \ No newline at end of file From a4081e2e841b6cebb4e2e10e762dc97be21632e5 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Sat, 11 Jan 2025 12:59:23 +0100 Subject: [PATCH 10/15] -Possible memory leaks change --- homework/shared_ptr/weak_ptr.hpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/homework/shared_ptr/weak_ptr.hpp b/homework/shared_ptr/weak_ptr.hpp index b956a106..9697b184 100644 --- a/homework/shared_ptr/weak_ptr.hpp +++ b/homework/shared_ptr/weak_ptr.hpp @@ -62,13 +62,13 @@ class weak_ptr { void reset() noexcept { if (control_block) { - control_block->weak_count--; - if (control_block->weak_count == 0 && control_block->shared_count == 0) { + --control_block->weak_count; + if (control_block->shared_count == 0 && control_block->weak_count == 0) { delete control_block; } - ptr = nullptr; - control_block = nullptr; } + ptr = nullptr; + control_block = nullptr; } std::size_t use_count() const noexcept { @@ -80,13 +80,14 @@ class weak_ptr { } shared_ptr lock() const noexcept { - if (expired()) { + if (expired() || !control_block) { return shared_ptr(); } + shared_ptr sp; - sp.ptr = ptr; - sp.control_block = control_block; - if (control_block) { + if (control_block->shared_count > 0) { + sp.ptr = ptr; + sp.control_block = control_block; ++control_block->shared_count; } return sp; From 3b4f2d353beb3d0d2b4cf81dd4bdb8fdb8882ad4 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Sat, 11 Jan 2025 13:18:07 +0100 Subject: [PATCH 11/15] -Deleted weak_ptr and went back to previous shared_ptr version --- homework/shared_ptr/shared_ptr.hpp | 120 ++++++++++++------------- homework/shared_ptr/weak_ptr.hpp | 103 --------------------- homework/shared_ptr/weak_ptr_tests.cpp | 48 ---------- 3 files changed, 57 insertions(+), 214 deletions(-) delete mode 100644 homework/shared_ptr/weak_ptr.hpp delete mode 100644 homework/shared_ptr/weak_ptr_tests.cpp diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 52798114..080fde6a 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -1,103 +1,97 @@ #pragma once #include -#include -#include namespace my { -template -class weak_ptr; // Forward declaration - template class shared_ptr { - friend class weak_ptr; +private: + T* ptr; -public: struct ControlBlock { - std::atomic shared_count; - std::atomic weak_count; - - ControlBlock() : shared_count(1), weak_count(0) {} + std::atomic shared_count; + std::atomic weak_count; + void (*deleter)(T*); + + ControlBlock() + : shared_count(1), weak_count(0), deleter(nullptr) {} }; + ControlBlock* control_block; - explicit shared_ptr(T* p = nullptr) +public: + explicit shared_ptr(T* p = nullptr) : ptr(p), control_block(new ControlBlock()) {} - - shared_ptr(const shared_ptr& other) + + shared_ptr(const shared_ptr& other) : ptr(other.ptr), control_block(other.control_block) { if (control_block) { ++control_block->shared_count; } } - shared_ptr& operator=(const shared_ptr& other) { - if (this != &other) { - reset(); - ptr = other.ptr; - control_block = other.control_block; - if (control_block) { - ++control_block->shared_count; - } - } + shared_ptr& operator=(const shared_ptr& otherSharedPtr) { + shared_ptr(otherSharedPtr).swap(*this); return *this; } - shared_ptr(shared_ptr&& other) noexcept - : ptr(other.ptr), control_block(other.control_block) { - other.ptr = nullptr; - other.control_block = nullptr; + shared_ptr(shared_ptr&& otherSharedPtr) noexcept + : ptr(otherSharedPtr.ptr), control_block(otherSharedPtr.control_block) { + otherSharedPtr.ptr = nullptr; + otherSharedPtr.control_block = nullptr; } - shared_ptr& operator=(shared_ptr&& other) noexcept { - if (this != &other) { - reset(); - ptr = other.ptr; - control_block = other.control_block; - other.ptr = nullptr; - other.control_block = nullptr; - } + shared_ptr& operator=(shared_ptr&& otherSharedPtr) noexcept { + shared_ptr(std::move(otherSharedPtr)).swap(*this); return *this; } ~shared_ptr() { - reset(); - } - - void swap(shared_ptr& other) noexcept { - std::swap(ptr, other.ptr); - std::swap(control_block, other.control_block); + if (control_block) { + if (--control_block->shared_count == 0) { + if (ptr && control_block->deleter) { + control_block->deleter(ptr); + } else { + delete ptr; + } + if (control_block->weak_count == 0) { + delete control_block; + } + } + } } - T* get() const noexcept { return ptr; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } - - std::size_t use_count() const noexcept { - return control_block ? control_block->shared_count.load() : 0; + T* get() const { return ptr; } + + size_t use_count() const { + return (control_block ? control_block->shared_count.load() : 0); } - explicit operator bool() const noexcept { return ptr != nullptr; } + explicit operator bool() const { return ptr != nullptr; } + + void swap(shared_ptr& otherSharedPtr) noexcept { + std::swap(ptr, otherSharedPtr.ptr); + std::swap(control_block, otherSharedPtr.control_block); + } void reset(T* p = nullptr) { - if (control_block) { - if (--control_block->shared_count == 0) { - delete ptr; - if (control_block->weak_count == 0) { - delete control_block; + if (p != ptr) { + if (control_block) { + if (--control_block->shared_count == 0) { + delete ptr; + if (control_block->weak_count == 0) { + delete control_block; + } } } - } - ptr = p; - if (p) { - control_block = new ControlBlock(); - } else { - control_block = nullptr; + ptr = p; + if (p) { + control_block = new ControlBlock(); + } else { + control_block = nullptr; + } } } - -private: - T* ptr; - ControlBlock* control_block; }; - -} // namespace my \ No newline at end of file +} // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/weak_ptr.hpp b/homework/shared_ptr/weak_ptr.hpp deleted file mode 100644 index 9697b184..00000000 --- a/homework/shared_ptr/weak_ptr.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef WEAK_PTR_HPP -#define WEAK_PTR_HPP - -#include "shared_ptr.hpp" -#include - -namespace my { - -template -class weak_ptr { - friend class shared_ptr; - -public: - weak_ptr() noexcept : ptr(nullptr), control_block(nullptr) {} - - weak_ptr(const shared_ptr& sp) noexcept - : ptr(sp.ptr), control_block(sp.control_block) { - if (control_block) { - control_block->weak_count++; - } - } - - weak_ptr(const weak_ptr& other) noexcept - : ptr(other.ptr), control_block(other.control_block) { - if (control_block) { - control_block->weak_count++; - } - } - - weak_ptr(weak_ptr&& other) noexcept - : ptr(other.ptr), control_block(other.control_block) { - other.ptr = nullptr; - other.control_block = nullptr; - } - - ~weak_ptr() { - reset(); - } - - weak_ptr& operator=(const weak_ptr& other) noexcept { - if (this != &other) { - reset(); - ptr = other.ptr; - control_block = other.control_block; - if (control_block) { - control_block->weak_count++; - } - } - return *this; - } - - weak_ptr& operator=(weak_ptr&& other) noexcept { - if (this != &other) { - reset(); - ptr = other.ptr; - control_block = other.control_block; - other.ptr = nullptr; - other.control_block = nullptr; - } - return *this; - } - - void reset() noexcept { - if (control_block) { - --control_block->weak_count; - if (control_block->shared_count == 0 && control_block->weak_count == 0) { - delete control_block; - } - } - ptr = nullptr; - control_block = nullptr; - } - - std::size_t use_count() const noexcept { - return control_block ? control_block->shared_count.load() : 0; - } - - bool expired() const noexcept { - return use_count() == 0; - } - - shared_ptr lock() const noexcept { - if (expired() || !control_block) { - return shared_ptr(); - } - - shared_ptr sp; - if (control_block->shared_count > 0) { - sp.ptr = ptr; - sp.control_block = control_block; - ++control_block->shared_count; - } - return sp; - } - -private: - T* ptr; - typename shared_ptr::ControlBlock* control_block; -}; - -} // namespace my - -#endif // WEAK_PTR_HPP \ No newline at end of file diff --git a/homework/shared_ptr/weak_ptr_tests.cpp b/homework/shared_ptr/weak_ptr_tests.cpp deleted file mode 100644 index 119c44ce..00000000 --- a/homework/shared_ptr/weak_ptr_tests.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "weak_ptr.hpp" -#include - -// Instantiate the template class for testing -template class my::weak_ptr; - -TEST(WeakPtrTest, DefaultConstructor) { - my::weak_ptr wp; - EXPECT_TRUE(wp.expired()); - EXPECT_EQ(wp.use_count(), 0); -} - -TEST(WeakPtrTest, UseCount) { - my::shared_ptr sp(new int(10)); - my::weak_ptr wp(sp); - EXPECT_EQ(wp.use_count(), 1); -} - -TEST(WeakPtrTest, Expired) { - my::shared_ptr sp(new int(20)); - my::weak_ptr wp(sp); - EXPECT_FALSE(wp.expired()); - sp.reset(); - EXPECT_TRUE(wp.expired()); -} - -TEST(WeakPtrTest, Reset) { - my::shared_ptr sp(new int(40)); - my::weak_ptr wp(sp); - wp.reset(); - EXPECT_TRUE(wp.expired()); -} - -TEST(WeakPtrTest, CopyConstructor) { - my::shared_ptr sp(new int(50)); - my::weak_ptr wp1(sp); - my::weak_ptr wp2(wp1); - EXPECT_EQ(wp1.use_count(), 1); - EXPECT_EQ(wp2.use_count(), 1); -} - -TEST(WeakPtrTest, MoveConstructor) { - my::shared_ptr sp(new int(60)); - my::weak_ptr wp1(sp); - my::weak_ptr wp2(std::move(wp1)); - EXPECT_EQ(wp2.use_count(), 1); - EXPECT_TRUE(wp1.expired()); -} \ No newline at end of file From 2e2ada74f0c4b2ef9b09c64c94bf630c4fac661e Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Sat, 11 Jan 2025 13:32:45 +0100 Subject: [PATCH 12/15] -Changed version of weak_ptr implementation --- homework/shared_ptr/shared_ptr.hpp | 9 +++ homework/shared_ptr/weak_ptr.hpp | 94 ++++++++++++++++++++++++++ homework/shared_ptr/weak_ptr_tests.cpp | 66 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 homework/shared_ptr/weak_ptr.hpp create mode 100644 homework/shared_ptr/weak_ptr_tests.cpp diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 080fde6a..f7219efa 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -3,6 +3,9 @@ namespace my { +template +class weak_ptr; // Forward declaration + template class shared_ptr { private: @@ -18,6 +21,12 @@ class shared_ptr { }; ControlBlock* control_block; + // Private constructor for weak_ptr::lock() + shared_ptr(T* p, ControlBlock* cb) noexcept + : ptr(p), control_block(cb) {} + + friend class weak_ptr; // Add this line to make weak_ptr a friend + public: explicit shared_ptr(T* p = nullptr) : ptr(p), control_block(new ControlBlock()) {} diff --git a/homework/shared_ptr/weak_ptr.hpp b/homework/shared_ptr/weak_ptr.hpp new file mode 100644 index 00000000..9ccf2173 --- /dev/null +++ b/homework/shared_ptr/weak_ptr.hpp @@ -0,0 +1,94 @@ +#pragma once +#include +#include "shared_ptr.hpp" + +namespace my { + +template +class weak_ptr { +private: + T* ptr{nullptr}; + typename shared_ptr::ControlBlock* control_block{nullptr}; + +public: + weak_ptr() noexcept = default; + + weak_ptr(const shared_ptr& shared) noexcept + : ptr(shared.ptr), control_block(shared.control_block) { + if (control_block) { + ++control_block->weak_count; + } + } + + weak_ptr(const weak_ptr& other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + if (control_block) { + ++control_block->weak_count; + } + } + + weak_ptr(weak_ptr&& other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + other.ptr = nullptr; + other.control_block = nullptr; + } + + weak_ptr& operator=(const weak_ptr& other) noexcept { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + if (control_block) { + ++control_block->weak_count; + } + } + return *this; + } + + weak_ptr& operator=(weak_ptr&& other) noexcept { + if (this != &other) { + reset(); + ptr = other.ptr; + control_block = other.control_block; + other.ptr = nullptr; + other.control_block = nullptr; + } + return *this; + } + + ~weak_ptr() { + reset(); + } + + void reset() noexcept { + if (control_block) { + if (--control_block->weak_count == 0 && control_block->shared_count == 0) { + delete control_block; + } + ptr = nullptr; + control_block = nullptr; + } + } + + size_t use_count() const noexcept { + return control_block ? control_block->shared_count.load() : 0; + } + + bool expired() const noexcept { + return use_count() == 0; + } + + shared_ptr lock() const noexcept { + if (expired()) { + return shared_ptr(); + } + + shared_ptr shared(ptr, control_block); + if (control_block) { + ++control_block->shared_count; + } + return shared; + } +}; + +} // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/weak_ptr_tests.cpp b/homework/shared_ptr/weak_ptr_tests.cpp new file mode 100644 index 00000000..8c4bf994 --- /dev/null +++ b/homework/shared_ptr/weak_ptr_tests.cpp @@ -0,0 +1,66 @@ +#include +#include "weak_ptr.hpp" + +template class my::weak_ptr; + +TEST(WeakPtrTest, DefaultConstructor) { + my::weak_ptr wp; + EXPECT_TRUE(wp.expired()); + EXPECT_EQ(wp.use_count(), 0); +} + +TEST(WeakPtrTest, ConstructFromSharedPtr) { + my::shared_ptr sp(new int(42)); + my::weak_ptr wp(sp); + + EXPECT_FALSE(wp.expired()); + EXPECT_EQ(wp.use_count(), 1); +} + +TEST(WeakPtrTest, LockMethod) { + my::shared_ptr sp(new int(42)); + my::weak_ptr wp(sp); + + auto locked = wp.lock(); + EXPECT_TRUE(locked); + EXPECT_EQ(*locked, 42); + EXPECT_EQ(locked.use_count(), 2); +} + +TEST(WeakPtrTest, ExpiredCheck) { + my::weak_ptr wp; + { + my::shared_ptr sp(new int(42)); + wp = sp; + EXPECT_FALSE(wp.expired()); + } + EXPECT_TRUE(wp.expired()); +} + +TEST(WeakPtrTest, CopyConstructor) { + my::shared_ptr sp(new int(42)); + my::weak_ptr wp1(sp); + my::weak_ptr wp2(wp1); + + EXPECT_EQ(wp1.use_count(), 1); + EXPECT_EQ(wp2.use_count(), 1); +} + +TEST(WeakPtrTest, MoveConstructor) { + my::shared_ptr sp(new int(42)); + my::weak_ptr wp1(sp); + my::weak_ptr wp2(std::move(wp1)); + + EXPECT_TRUE(wp1.expired()); + EXPECT_FALSE(wp2.expired()); + EXPECT_EQ(wp2.use_count(), 1); +} + +TEST(WeakPtrTest, Reset) { + my::shared_ptr sp(new int(42)); + my::weak_ptr wp(sp); + + wp.reset(); + EXPECT_TRUE(wp.expired()); + EXPECT_EQ(wp.use_count(), 0); +} \ No newline at end of file From b9a93b72d37504e4e106a7a880406579d7165a34 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Wed, 22 Jan 2025 22:47:47 +0100 Subject: [PATCH 13/15] -Added make_shared implementation --- homework/CMakeLists.txt | 5 +++- homework/shared_ptr/make_shared.hpp | 23 +++++++++++++++ homework/shared_ptr/make_shared_tests.cpp | 36 +++++++++++++++++++++++ homework/shared_ptr/shared_ptr.hpp | 23 ++++++++++++--- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 homework/shared_ptr/make_shared.hpp create mode 100644 homework/shared_ptr/make_shared_tests.cpp diff --git a/homework/CMakeLists.txt b/homework/CMakeLists.txt index ce6c61f1..61b37541 100644 --- a/homework/CMakeLists.txt +++ b/homework/CMakeLists.txt @@ -22,12 +22,15 @@ FetchContent_MakeAvailable(googletest) #Test executable add_executable(shared_ptr_tests shared_ptr/shared_ptr_tests.cpp) add_executable(weak_ptr_tests shared_ptr/weak_ptr_tests.cpp) +add_executable(make_shared_tests shared_ptr/make_shared_tests.cpp) #Link GTest target_link_libraries(shared_ptr_tests GTest::gtest GTest::gtest_main) target_link_libraries(weak_ptr_tests GTest::gtest GTest::gtest_main) +target_link_libraries(make_shared_tests GTest::gtest GTest::gtest_main) enable_testing() add_test(NAME SharedPtrTests COMMAND shared_ptr_tests) -add_test(NAME WeakPtrTests COMMAND weak_ptr_tests) \ No newline at end of file +add_test(NAME WeakPtrTests COMMAND weak_ptr_tests) +add_test(NAME MakeSharedTests COMMAND make_shared_tests) \ No newline at end of file diff --git a/homework/shared_ptr/make_shared.hpp b/homework/shared_ptr/make_shared.hpp new file mode 100644 index 00000000..168cc416 --- /dev/null +++ b/homework/shared_ptr/make_shared.hpp @@ -0,0 +1,23 @@ +#pragma once +#include +#include "shared_ptr.hpp" + +namespace my { + +template +shared_ptr make_shared(Args&&... args) { + using CombinedBlock = typename shared_ptr::ControlBlockWithObject; + auto* combined = new CombinedBlock(std::forward(args)...); + + shared_ptr result(&combined->object, &combined->control); + result.control_block->deleter = [](T* ptr) { + auto* combined_ptr = reinterpret_cast( + reinterpret_cast(ptr) - offsetof(CombinedBlock, object) + ); + delete combined_ptr; + }; + + return result; +} + +} // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/make_shared_tests.cpp b/homework/shared_ptr/make_shared_tests.cpp new file mode 100644 index 00000000..0bb68213 --- /dev/null +++ b/homework/shared_ptr/make_shared_tests.cpp @@ -0,0 +1,36 @@ +#include +#include "make_shared.hpp" +#include "weak_ptr.hpp" +#include + +struct TestStruct { + int x; + std::string str; + + TestStruct(int x_, std::string str_) + : x(x_), str(std::move(str_)) {} +}; + +TEST(MakeSharedTest, BasicType) { + auto sp = my::make_shared(42); + EXPECT_EQ(*sp, 42); + EXPECT_EQ(sp.use_count(), 1); +} + +TEST(MakeSharedTest, CustomType) { + auto sp = my::make_shared(42, "test"); + EXPECT_EQ(sp->x, 42); + EXPECT_EQ(sp->str, "test"); + EXPECT_EQ(sp.use_count(), 1); +} + +TEST(MakeSharedTest, WeakPtr) { + auto sp = my::make_shared(42); + my::weak_ptr wp(sp); + + EXPECT_EQ(wp.use_count(), 1); + EXPECT_FALSE(wp.expired()); + + auto locked = wp.lock(); + EXPECT_EQ(*locked, 42); +} \ No newline at end of file diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index f7219efa..60c6c3bd 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -1,10 +1,12 @@ #pragma once #include +#include namespace my { -template -class weak_ptr; // Forward declaration +template class weak_ptr; // Forward declaration +template class shared_ptr; // Forward declaration +template shared_ptr make_shared(Args&&... args); template class shared_ptr { @@ -19,13 +21,26 @@ class shared_ptr { ControlBlock() : shared_count(1), weak_count(0), deleter(nullptr) {} }; + + struct ControlBlockWithObject { + ControlBlock control; + T object; + + template + ControlBlockWithObject(Args&&... args) + : control() + , object(std::forward(args)...) {} + }; + ControlBlock* control_block; - // Private constructor for weak_ptr::lock() + // Private constructor for weak_ptr::lock() and make_shared shared_ptr(T* p, ControlBlock* cb) noexcept : ptr(p), control_block(cb) {} - friend class weak_ptr; // Add this line to make weak_ptr a friend + friend class weak_ptr; + template + friend shared_ptr make_shared(Args&&... args); public: explicit shared_ptr(T* p = nullptr) From 466ac3ce18bb31072463bd11a020514ad24e8e13 Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Wed, 22 Jan 2025 23:17:43 +0100 Subject: [PATCH 14/15] -Changes within shared_ptr to fix errors --- homework/shared_ptr/shared_ptr.hpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 60c6c3bd..2d90e924 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -72,13 +72,17 @@ class shared_ptr { ~shared_ptr() { if (control_block) { if (--control_block->shared_count == 0) { - if (ptr && control_block->deleter) { + if (control_block->deleter) { control_block->deleter(ptr); + control_block = nullptr; + ptr = nullptr; } else { delete ptr; - } - if (control_block->weak_count == 0) { - delete control_block; + if (control_block->weak_count == 0) { + delete control_block; + } + control_block = nullptr; + ptr = nullptr; } } } From ed80002787e8950a0e41308068688389aaee488d Mon Sep 17 00:00:00 2001 From: MichalMarciniakGS Date: Wed, 22 Jan 2025 23:19:10 +0100 Subject: [PATCH 15/15] -Formatting --- homework/shared_ptr/make_shared.hpp | 11 +++++------ homework/shared_ptr/make_shared_tests.cpp | 10 +++++----- homework/shared_ptr/shared_ptr.hpp | 16 +++++++++------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/homework/shared_ptr/make_shared.hpp b/homework/shared_ptr/make_shared.hpp index 168cc416..db5e1b03 100644 --- a/homework/shared_ptr/make_shared.hpp +++ b/homework/shared_ptr/make_shared.hpp @@ -4,20 +4,19 @@ namespace my { -template +template shared_ptr make_shared(Args&&... args) { using CombinedBlock = typename shared_ptr::ControlBlockWithObject; auto* combined = new CombinedBlock(std::forward(args)...); - + shared_ptr result(&combined->object, &combined->control); result.control_block->deleter = [](T* ptr) { auto* combined_ptr = reinterpret_cast( - reinterpret_cast(ptr) - offsetof(CombinedBlock, object) - ); + reinterpret_cast(ptr) - offsetof(CombinedBlock, object)); delete combined_ptr; }; - + return result; } -} // namespace my \ No newline at end of file +} // namespace my \ No newline at end of file diff --git a/homework/shared_ptr/make_shared_tests.cpp b/homework/shared_ptr/make_shared_tests.cpp index 0bb68213..9d0b5927 100644 --- a/homework/shared_ptr/make_shared_tests.cpp +++ b/homework/shared_ptr/make_shared_tests.cpp @@ -1,13 +1,13 @@ #include +#include #include "make_shared.hpp" #include "weak_ptr.hpp" -#include struct TestStruct { int x; std::string str; - - TestStruct(int x_, std::string str_) + + TestStruct(int x_, std::string str_) : x(x_), str(std::move(str_)) {} }; @@ -27,10 +27,10 @@ TEST(MakeSharedTest, CustomType) { TEST(MakeSharedTest, WeakPtr) { auto sp = my::make_shared(42); my::weak_ptr wp(sp); - + EXPECT_EQ(wp.use_count(), 1); EXPECT_FALSE(wp.expired()); - + auto locked = wp.lock(); EXPECT_EQ(*locked, 42); } \ No newline at end of file diff --git a/homework/shared_ptr/shared_ptr.hpp b/homework/shared_ptr/shared_ptr.hpp index 2d90e924..3ddb836d 100644 --- a/homework/shared_ptr/shared_ptr.hpp +++ b/homework/shared_ptr/shared_ptr.hpp @@ -4,9 +4,12 @@ namespace my { -template class weak_ptr; // Forward declaration -template class shared_ptr; // Forward declaration -template shared_ptr make_shared(Args&&... args); +template +class weak_ptr; // Forward declaration +template +class shared_ptr; // Forward declaration +template +shared_ptr make_shared(Args&&... args); template class shared_ptr { @@ -26,10 +29,9 @@ class shared_ptr { ControlBlock control; T object; - template + template ControlBlockWithObject(Args&&... args) - : control() - , object(std::forward(args)...) {} + : control(), object(std::forward(args)...) {} }; ControlBlock* control_block; @@ -39,7 +41,7 @@ class shared_ptr { : ptr(p), control_block(cb) {} friend class weak_ptr; - template + template friend shared_ptr make_shared(Args&&... args); public: