From 8c8aa2358e0861978ba39d253cabf082ef3c6451 Mon Sep 17 00:00:00 2001 From: AndreaRigoni Date: Thu, 16 Apr 2026 11:30:50 +0000 Subject: [PATCH] feat: add Boost serialization support for SmartPointer and include standard smart pointer headers --- src/Core/SmartPointer.h | 371 +++++++++++++++++++++------------------- 1 file changed, 198 insertions(+), 173 deletions(-) diff --git a/src/Core/SmartPointer.h b/src/Core/SmartPointer.h index 242b4d5..b1f03a7 100644 --- a/src/Core/SmartPointer.h +++ b/src/Core/SmartPointer.h @@ -37,210 +37,235 @@ namespace uLib { /** - * @brief Internal control block for shared ownership across polymorphic SmartPointers. + * @brief Internal control block for shared ownership across polymorphic + * SmartPointers. */ struct ControlBlock { - std::atomic count; - std::function deleter; + std::atomic count; + std::function deleter; - explicit ControlBlock(uint32_t initial_count = 1) : count(initial_count) {} + explicit ControlBlock(uint32_t initial_count = 1) : count(initial_count) {} private: - friend class boost::serialization::access; - template - void serialize(Archive& ar, const unsigned int /*version*/) { - // ControlBlock identity is tracked by Boost via the cb pointer in ReferenceCounter. - // We only save the count value. - uint32_t c = count.load(); - ar & boost::serialization::make_nvp("count", c); - if constexpr (Archive::is_loading::value) count.store(c); - } + friend class boost::serialization::access; + template + void serialize(Archive &ar, const unsigned int /*version*/) { + // ControlBlock identity is tracked by Boost via the cb pointer in + // ReferenceCounter. We only save the count value. + uint32_t c = count.load(); + ar &boost::serialization::make_nvp("count", c); + if constexpr (Archive::is_loading::value) + count.store(c); + } }; /** * @brief A smart pointer implementation inspired by std::shared_ptr. */ -template -class SmartPointer { +template class SmartPointer { public: - using element_type = T; + using element_type = T; - /** - * @brief Nested reference counter structure. - * Preserved as a nested template for Boost serialization compatibility. - */ - struct ReferenceCounter { - T* ptr; - ControlBlock* cb; + /** + * @brief Nested reference counter structure. + * Preserved as a nested template for Boost serialization compatibility. + */ + struct ReferenceCounter { + T *ptr; + ControlBlock *cb; - ReferenceCounter() : ptr(nullptr), cb(nullptr) {} - explicit ReferenceCounter(T* p) : ptr(p), cb(new ControlBlock(1)) { - cb->deleter = [p]() { delete p; }; - } - template - ReferenceCounter(T* p, D d) : ptr(p), cb(new ControlBlock(1)) { - cb->deleter = [p, d]() { d(p); }; - } - - private: - friend class boost::serialization::access; - template - void serialize(Archive& ar, const unsigned int /*version*/) { - ar & boost::serialization::make_nvp("ptr", ptr); - ar & boost::serialization::make_nvp("cb", cb); - } - }; - - SmartPointer() : m_counter(nullptr) { - if constexpr (std::is_default_constructible_v) { - m_counter = new ReferenceCounter(new T()); - } + ReferenceCounter() : ptr(nullptr), cb(nullptr) {} + explicit ReferenceCounter(T *p) : ptr(p), cb(new ControlBlock(1)) { + cb->deleter = [p]() { delete p; }; } - - SmartPointer(std::nullptr_t) noexcept : m_counter(nullptr) {} - - /** - * @brief Constructor from raw pointer (Implicit conversion allowed for legacy compatibility). - */ - SmartPointer(T* ptr) : m_counter(nullptr) { - if (ptr) m_counter = new ReferenceCounter(ptr); - } - template - SmartPointer(T* ptr, D deleter) : m_counter(nullptr) { - if (ptr) m_counter = new ReferenceCounter(ptr, deleter); + ReferenceCounter(T *p, D d) : ptr(p), cb(new ControlBlock(1)) { + cb->deleter = [p, d]() { d(p); }; } - SmartPointer(T &ref) : m_counter(new ReferenceCounter(&ref, [](T*){})) { } - - SmartPointer(const SmartPointer& other) noexcept : m_counter(nullptr) { - acquire(other.m_counter); - } - - SmartPointer(const SmartPointer* other) noexcept : m_counter(nullptr) { - if (other) acquire(other->m_counter); - } - - template >> - SmartPointer(const SmartPointer& other) noexcept : m_counter(nullptr) { - if (other.m_counter) { - m_counter = new ReferenceCounter(); - m_counter->ptr = static_cast(other.m_counter->ptr); - m_counter->cb = other.m_counter->cb; - if (m_counter->cb) m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); - } - } - - template - SmartPointer(const SmartPointer& other, T* ptr) noexcept : m_counter(nullptr) { - if (other.m_counter) { - m_counter = new ReferenceCounter(); - m_counter->ptr = ptr; - m_counter->cb = other.m_counter->cb; - if (m_counter->cb) m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); - } - } - - SmartPointer(SmartPointer&& other) noexcept : m_counter(other.m_counter) { - other.m_counter = nullptr; - } - - ~SmartPointer() { release(); } - - SmartPointer& operator=(const SmartPointer& other) noexcept { - if (this != &other) { - release(); - acquire(other.m_counter); - } - return *this; - } - - SmartPointer& operator=(T* ptr) noexcept { - reset(ptr); - return *this; - } - - SmartPointer& operator=(SmartPointer&& other) noexcept { - if (this != &other) { - release(); - m_counter = other.m_counter; - other.m_counter = nullptr; - } - return *this; - } - - void reset(T* ptr = nullptr) { - release(); - if (ptr) m_counter = new ReferenceCounter(ptr); - } - - void swap(SmartPointer& other) noexcept { - std::swap(m_counter, other.m_counter); - } - - T& operator*() const noexcept { return *(m_counter->ptr); } - T* operator->() const noexcept { return m_counter->ptr; } - T* get() const noexcept { return m_counter ? m_counter->ptr : nullptr; } - T* Get() const noexcept { return get(); } - operator T*() const noexcept { return get(); } - - uint32_t use_count() const noexcept { - return (m_counter && m_counter->cb) ? m_counter->cb->count.load(std::memory_order_relaxed) : 0; - } - - bool unique() const noexcept { return use_count() == 1; } - explicit operator bool() const noexcept { return get() != nullptr; } - - BOOST_SERIALIZATION_SPLIT_MEMBER() - + private: + friend class boost::serialization::access; template - void save(Archive& ar, const unsigned int /*version*/) const { - ar & boost::serialization::make_nvp("counter", m_counter); + void serialize(Archive &ar, const unsigned int /*version*/) { + ar &boost::serialization::make_nvp("ptr", ptr); + ar &boost::serialization::make_nvp("cb", cb); } + }; - template - void load(Archive& ar, const unsigned int /*version*/) { - release(); - ar & boost::serialization::make_nvp("counter", m_counter); - if (m_counter && m_counter->cb) { - m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); - } + SmartPointer() : m_counter(nullptr) { + if constexpr (std::is_default_constructible_v) { + m_counter = new ReferenceCounter(new T()); } + } + + SmartPointer(std::nullptr_t) noexcept : m_counter(nullptr) {} + + /** + * @brief Constructor from raw pointer (Implicit conversion allowed for legacy + * compatibility). + */ + SmartPointer(T *ptr) : m_counter(nullptr) { + if (ptr) + m_counter = new ReferenceCounter(ptr); + } + + template SmartPointer(T *ptr, D deleter) : m_counter(nullptr) { + if (ptr) + m_counter = new ReferenceCounter(ptr, deleter); + } + + SmartPointer(T &ref) : m_counter(new ReferenceCounter(&ref, [](T *) {})) {} + + SmartPointer(const SmartPointer &other) noexcept : m_counter(nullptr) { + acquire(other.m_counter); + } + + SmartPointer(const SmartPointer *other) noexcept : m_counter(nullptr) { + if (other) + acquire(other->m_counter); + } + + template >> + SmartPointer(const SmartPointer &other) noexcept : m_counter(nullptr) { + if (other.m_counter) { + m_counter = new ReferenceCounter(); + m_counter->ptr = static_cast(other.m_counter->ptr); + m_counter->cb = other.m_counter->cb; + if (m_counter->cb) + m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); + } + } + + template + SmartPointer(const SmartPointer &other, T *ptr) noexcept + : m_counter(nullptr) { + if (other.m_counter) { + m_counter = new ReferenceCounter(); + m_counter->ptr = ptr; + m_counter->cb = other.m_counter->cb; + if (m_counter->cb) + m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); + } + } + + SmartPointer(SmartPointer &&other) noexcept : m_counter(other.m_counter) { + other.m_counter = nullptr; + } + + ~SmartPointer() { release(); } + + SmartPointer &operator=(const SmartPointer &other) noexcept { + if (this != &other) { + release(); + acquire(other.m_counter); + } + return *this; + } + + SmartPointer &operator=(T *ptr) noexcept { + reset(ptr); + return *this; + } + + SmartPointer &operator=(SmartPointer &&other) noexcept { + if (this != &other) { + release(); + m_counter = other.m_counter; + other.m_counter = nullptr; + } + return *this; + } + + void reset(T *ptr = nullptr) { + release(); + if (ptr) + m_counter = new ReferenceCounter(ptr); + } + + void swap(SmartPointer &other) noexcept { + std::swap(m_counter, other.m_counter); + } + + T &operator*() const noexcept { return *(m_counter->ptr); } + T *operator->() const noexcept { return m_counter->ptr; } + T *get() const noexcept { return m_counter ? m_counter->ptr : nullptr; } + T *Get() const noexcept { return get(); } + operator T *() const noexcept { return get(); } + + uint32_t use_count() const noexcept { + return (m_counter && m_counter->cb) + ? m_counter->cb->count.load(std::memory_order_relaxed) + : 0; + } + + bool unique() const noexcept { return use_count() == 1; } + explicit operator bool() const noexcept { return get() != nullptr; } + + BOOST_SERIALIZATION_SPLIT_MEMBER() + + template + void save(Archive &ar, const unsigned int /*version*/) const { + ar &boost::serialization::make_nvp("counter", m_counter); + } + + template + void load(Archive &ar, const unsigned int /*version*/) { + release(); + ar &boost::serialization::make_nvp("counter", m_counter); + if (m_counter && m_counter->cb) { + m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); + } + } private: - template friend class SmartPointer; - friend class boost::serialization::access; + template friend class SmartPointer; + friend class boost::serialization::access; - ReferenceCounter* m_counter; + ReferenceCounter *m_counter; - void acquire(ReferenceCounter* c) noexcept { - if (c) { - m_counter = new ReferenceCounter(); - m_counter->ptr = c->ptr; - m_counter->cb = c->cb; - if (m_counter->cb) m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); - } + void acquire(ReferenceCounter *c) noexcept { + if (c) { + m_counter = new ReferenceCounter(); + m_counter->ptr = c->ptr; + m_counter->cb = c->cb; + if (m_counter->cb) + m_counter->cb->count.fetch_add(1, std::memory_order_relaxed); } + } - void release() noexcept { - if (m_counter) { - if (m_counter->cb && m_counter->cb->count.fetch_sub(1, std::memory_order_acq_rel) == 1) { - if (m_counter->cb->deleter) m_counter->cb->deleter(); - delete m_counter->cb; - } - delete m_counter; - m_counter = nullptr; - } + void release() noexcept { + if (m_counter) { + if (m_counter->cb && + m_counter->cb->count.fetch_sub(1, std::memory_order_acq_rel) == 1) { + if (m_counter->cb->deleter) + m_counter->cb->deleter(); + delete m_counter->cb; + } + delete m_counter; + m_counter = nullptr; } + } }; -template SmartPointer static_pointer_cast(const SmartPointer& r) noexcept { return SmartPointer(r, static_cast(r.get())); } -template SmartPointer dynamic_pointer_cast(const SmartPointer& r) noexcept { - if (auto p = dynamic_cast(r.get())) return SmartPointer(r, p); - return SmartPointer(nullptr); +template +SmartPointer static_pointer_cast(const SmartPointer &r) noexcept { + return SmartPointer(r, static_cast(r.get())); +} +template +SmartPointer dynamic_pointer_cast(const SmartPointer &r) noexcept { + if (auto p = dynamic_cast(r.get())) + return SmartPointer(r, p); + return SmartPointer(nullptr); +} +template +SmartPointer const_pointer_cast(const SmartPointer &r) noexcept { + return SmartPointer(r, const_cast(r.get())); +} +template +SmartPointer reinterpret_pointer_cast(const SmartPointer &r) noexcept { + return SmartPointer(r, reinterpret_cast(r.get())); } -template SmartPointer const_pointer_cast(const SmartPointer& r) noexcept { return SmartPointer(r, const_cast(r.get())); } -template SmartPointer reinterpret_pointer_cast(const SmartPointer& r) noexcept { return SmartPointer(r, reinterpret_cast(r.get())); } } // namespace uLib