From 6b6028434d12a4e0533fd10b1a22e6f21c21f5f3 Mon Sep 17 00:00:00 2001 From: EnderIce2 Date: Fri, 9 May 2025 07:06:25 +0000 Subject: [PATCH] feat(kernel/std): :sparkles: implement std::shared_ptr --- Kernel/include_std/memory | 423 +++++++++++++++++++++++++++++++------- 1 file changed, 353 insertions(+), 70 deletions(-) diff --git a/Kernel/include_std/memory b/Kernel/include_std/memory index 9ec5ca03..e1c8f428 100644 --- a/Kernel/include_std/memory +++ b/Kernel/include_std/memory @@ -19,9 +19,11 @@ #include #include +#include #include #include #include +#include #include #include @@ -619,146 +621,427 @@ namespace std constexpr std::allocator_arg_t allocator_arg{}; - template - class auto_ptr; - - template <> - class auto_ptr; - template class weak_ptr; template class shared_ptr { + private: + struct control_block_base + { + long ref_count; + virtual void destroy() = 0; + control_block_base() : ref_count(1) {} + virtual ~control_block_base() = default; + }; + + template + struct control_block_impl : control_block_base + { + Y *ptr; + Deleter deleter; + void destroy() override { deleter(ptr); } + control_block_impl(Y *p, Deleter d) : ptr(p), deleter(d) {} + ~control_block_impl() override {} + }; + + struct control_block_default : control_block_base + { + T *ptr; + void destroy() override { delete ptr; } + control_block_default(T *p) : ptr(p) {} + ~control_block_default() override {} + }; + + template + struct control_block_alloc : control_block_base + { + Y *ptr; + Deleter deleter; + Alloc alloc; + void destroy() override { deleter(ptr); } + control_block_alloc(Y *p, Deleter d, Alloc a) : ptr(p), deleter(d), alloc(a) {} + ~control_block_alloc() override {} + + void *operator new(std::size_t sz, Alloc &a) + { + using AllocTraits = std::allocator_traits; + return AllocTraits::allocate(a, sz); + } + + void operator delete(void *p, std::size_t sz) + { + ::operator delete(p); + } + }; + + control_block_base *cb; + public: using weak_type = std::weak_ptr; using element_type = std::remove_extent_t; - constexpr shared_ptr() noexcept; - constexpr shared_ptr(std::nullptr_t) noexcept; + constexpr shared_ptr() noexcept : cb(nullptr) {} + constexpr shared_ptr(std::nullptr_t) noexcept : cb(nullptr) {} template - explicit shared_ptr(Y *ptr); + explicit shared_ptr(Y *ptr) : cb(ptr ? new control_block_default(ptr) : nullptr) {} template - shared_ptr(Y *ptr, Deleter d); + shared_ptr(Y *ptr, Deleter d) : cb(ptr ? new control_block_impl(ptr, d) : nullptr) {} template - shared_ptr(std::nullptr_t ptr, Deleter d); + shared_ptr(std::nullptr_t ptr, Deleter d) : cb(nullptr) {} template - shared_ptr(Y *ptr, Deleter d, Alloc alloc); + shared_ptr(Y *ptr, Deleter d, Alloc alloc) + : cb(ptr ? new(alloc) control_block_alloc(ptr, d, alloc) : nullptr) {} template - shared_ptr(std::nullptr_t ptr, Deleter d, Alloc alloc); + shared_ptr(std::nullptr_t ptr, Deleter d, Alloc alloc) : cb(nullptr) {} template - shared_ptr(const shared_ptr &r, element_type *ptr) noexcept; + shared_ptr(const shared_ptr &r, element_type *ptr) noexcept : cb(r.cb) + { + if (cb) + ++cb->ref_count; + } template - shared_ptr(shared_ptr &&r, element_type *ptr) noexcept; + shared_ptr(shared_ptr &&r, element_type *ptr) noexcept : cb(r.cb) { r.cb = nullptr; } - shared_ptr(const shared_ptr &r) noexcept; + shared_ptr(const shared_ptr &r) noexcept : cb(r.cb) + { + if (cb) + ++cb->ref_count; + } template - shared_ptr(const shared_ptr &r) noexcept; + shared_ptr(const shared_ptr &r) noexcept : cb(r.cb) + { + if (cb) + ++cb->ref_count; + } - shared_ptr(shared_ptr &&r) noexcept; + shared_ptr(shared_ptr &&r) noexcept : cb(r.cb) { r.cb = nullptr; } template - shared_ptr(shared_ptr &&r) noexcept; + shared_ptr(shared_ptr &&r) noexcept : cb(r.cb) { r.cb = nullptr; } template - explicit shared_ptr(const std::weak_ptr &r); - - template - shared_ptr(std::auto_ptr &&r); + explicit shared_ptr(const std::weak_ptr &r) : cb(nullptr) { /* Not implemented */ } template - shared_ptr(std::unique_ptr &&r); + shared_ptr(std::unique_ptr &&r) : cb(r.get() ? new control_block_impl(r.release(), Deleter()) : nullptr) {} - ~shared_ptr(); + ~shared_ptr() + { + if (cb) + { + if (--cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + } + } - shared_ptr &operator=(const shared_ptr &r) noexcept; + shared_ptr &operator=(const shared_ptr &r) noexcept + { + if (this != &r) + { + if (cb && --cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + cb = r.cb; + if (cb) + ++cb->ref_count; + } + return *this; + } template - shared_ptr &operator=(const shared_ptr &r) noexcept; + shared_ptr &operator=(const shared_ptr &r) noexcept + { + if (cb && --cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + cb = r.cb; + if (cb) + ++cb->ref_count; + return *this; + } - shared_ptr &operator=(shared_ptr &&r) noexcept; + shared_ptr &operator=(shared_ptr &&r) noexcept + { + if (this != &r) + { + if (cb && --cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + cb = r.cb; + r.cb = nullptr; + } + return *this; + } template - shared_ptr &operator=(shared_ptr &&r) noexcept; - - template - shared_ptr &operator=(std::auto_ptr &&r); + shared_ptr &operator=(shared_ptr &&r) noexcept + { + if (cb && --cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + cb = r.cb; + r.cb = nullptr; + return *this; + } template - shared_ptr &operator=(std::unique_ptr &&r); + shared_ptr &operator=(std::unique_ptr &&r) + { + reset(r.get(), Deleter()); + r.release(); + return *this; + } - void reset() noexcept; + void reset() noexcept + { + if (cb && --cb->ref_count == 0) + { + cb->destroy(); + delete cb; + } + cb = nullptr; + } template - void reset(Y *ptr); + void reset(Y *ptr) + { + reset(); + if (ptr) + cb = new control_block_default(ptr); + } template - void reset(Y *ptr, Deleter d); + void reset(Y *ptr, Deleter d) + { + reset(); + if (ptr) + cb = new control_block_impl(ptr, d); + } template - void reset(Y *ptr, Deleter d, Alloc alloc); + void reset(Y *ptr, Deleter d, Alloc alloc) + { + reset(); + if (ptr) + cb = new (alloc) control_block_alloc(ptr, d, alloc); + } - void swap(shared_ptr &r) noexcept; + void swap(shared_ptr &r) noexcept + { + control_block_base *tmp = cb; + cb = r.cb; + r.cb = tmp; + } - T *get() const noexcept; - - // element_type *get() const noexcept; - - T &operator*() const noexcept; - - T *operator->() const noexcept; - - element_type &operator[](std::ptrdiff_t idx) const; - - long use_count() const noexcept; - - bool unique() const noexcept; - - explicit operator bool() const noexcept { return get() != nullptr; } + element_type *get() const noexcept { return cb ? static_cast(cb)->ptr : nullptr; } + T &operator*() const noexcept { return *get(); } + T *operator->() const noexcept { return get(); } + element_type &operator[](std::ptrdiff_t idx) const { return get()[idx]; } + long use_count() const noexcept { return cb ? cb->ref_count : 0; } + explicit operator bool() const noexcept { return cb != nullptr; } template - bool owner_before(const shared_ptr &other) const noexcept; + bool owner_before(const shared_ptr &other) const noexcept { return cb < other.cb; } template - bool owner_before(const std::weak_ptr &other) const noexcept; - - std::size_t owner_hash() const noexcept; - - template - bool owner_equal(const std::shared_ptr &other) const noexcept; - - template - bool owner_equal(const std::weak_ptr &other) const noexcept; + bool owner_before(const std::weak_ptr &other) const noexcept { return cb < other.cb; } }; template - shared_ptr make_shared(Args &&...args); + shared_ptr make_shared(Args &&...args) { return shared_ptr(new T(std::forward(args)...)); } template - shared_ptr make_shared(std::size_t N); + shared_ptr make_shared(std::size_t N) { return shared_ptr(new T[N]); } template - shared_ptr make_shared(); + shared_ptr make_shared() { return shared_ptr(new T); } template - shared_ptr make_shared(std::size_t N, const std::remove_extent_t &u); + shared_ptr make_shared(std::size_t N, const std::remove_extent_t &u) { return shared_ptr(new T[N](u)); } template - shared_ptr make_shared(const std::remove_extent_t &u); + shared_ptr make_shared(const std::remove_extent_t &u) { return shared_ptr(new T(u)); } template - shared_ptr make_shared_for_overwrite(); + shared_ptr make_shared_for_overwrite() { return shared_ptr(new T); } template - shared_ptr make_shared_for_overwrite(std::size_t N); + shared_ptr make_shared_for_overwrite(std::size_t N) { return shared_ptr(new T[N]); } + template + shared_ptr allocate_shared(const Alloc &alloc, Args &&...args); + + template + shared_ptr allocate_shared(const Alloc &alloc, std::size_t N); + + template + shared_ptr allocate_shared(const Alloc &alloc); + + template + shared_ptr allocate_shared(const Alloc &alloc, std::size_t N, const std::remove_extent_t &u); + + template + shared_ptr allocate_shared(const Alloc &alloc, const std::remove_extent_t &u); + + template + shared_ptr allocate_shared_for_overwrite(const Alloc &alloc); + + template + shared_ptr allocate_shared_for_overwrite(const Alloc &alloc, std::size_t N); + + template + std::shared_ptr static_pointer_cast(const std::shared_ptr &r) noexcept + { + auto p = static_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + std::shared_ptr static_pointer_cast(std::shared_ptr &&r) noexcept + { + auto p = static_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + std::shared_ptr dynamic_pointer_cast(const std::shared_ptr &r) noexcept + { + if (auto p = dynamic_cast::element_type *>(r.get())) + return std::shared_ptr{r, p}; + else + return std::shared_ptr{}; + } + + template + std::shared_ptr dynamic_pointer_cast(std::shared_ptr &&r) noexcept + { + if (auto p = dynamic_cast::element_type *>(r.get())) + return std::shared_ptr{r, p}; + else + return std::shared_ptr{}; + } + + template + std::shared_ptr const_pointer_cast(const std::shared_ptr &r) noexcept + { + auto p = const_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + std::shared_ptr const_pointer_cast(std::shared_ptr &&r) noexcept + { + auto p = const_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + std::shared_ptr reinterpret_pointer_cast(const std::shared_ptr &r) noexcept + { + auto p = reinterpret_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + std::shared_ptr reinterpret_pointer_cast(std::shared_ptr &&r) noexcept + { + auto p = reinterpret_cast::element_type *>(r.get()); + return std::shared_ptr{r, p}; + } + + template + Deleter *get_deleter(const std::shared_ptr &p) noexcept { return p.get_deleter(); } + + template + bool operator==(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return lhs.get() == rhs.get(); } + + template + bool operator!=(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return !(lhs == rhs); } + + // template + // bool operator<(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return std::less()(lhs.get(), rhs.get()); } + + template + bool operator>(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return rhs < lhs; } + + template + bool operator<=(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return !(rhs < lhs); } + + template + bool operator>=(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return !(lhs < rhs); } + + // template + // std::strong_ordering operator<=>(const std::shared_ptr &lhs, const std::shared_ptr &rhs) noexcept { return std::compare_three_way{}(x.get(), y.get()); } + + template + bool operator==(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return !lhs; } + + template + bool operator==(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return !rhs; } + + template + bool operator!=(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return (bool)lhs; } + + template + bool operator!=(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return (bool)rhs; } + + // template + // bool operator<(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return std::less::element_type *>()(lhs.get(), nullptr); } + + // template + // bool operator<(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return std::less::element_type *>()(nullptr, rhs.get()); } + + template + bool operator>(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return nullptr < lhs; } + + template + bool operator>(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return rhs < nullptr; } + + template + bool operator<=(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return !(nullptr < lhs); } + + template + bool operator<=(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return !(rhs < nullptr); } + + template + bool operator>=(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return !(lhs < nullptr); } + + template + bool operator>=(std::nullptr_t, const std::shared_ptr &rhs) noexcept { return !(nullptr < rhs); } + + // template + // std::strong_ordering operator<=>(const std::shared_ptr &lhs, std::nullptr_t) noexcept { return std::compare_three_way{}(x.get(), static_cast::element_type*>(nullptr)); } + + // template + // std::basic_ostream &operator<<(std::basic_ostream &os, const std::shared_ptr &ptr) { return os << ptr.get(); } + + template + void swap(std::shared_ptr &lhs, std::shared_ptr &rhs) noexcept { lhs.swap(rhs); } + + // template + // struct std::atomic>; + + template + struct hash>; }