diff --git a/src/Core/SmartPointer.h b/src/Core/SmartPointer.h index ac49cda..bac7d1e 100644 --- a/src/Core/SmartPointer.h +++ b/src/Core/SmartPointer.h @@ -23,89 +23,239 @@ //////////////////////////////////////////////////////////////////////////////*/ - - #ifndef U_CORE_SMARTPOINTER_H #define U_CORE_SMARTPOINTER_H +#include +#include +#include namespace uLib { +/** + * @brief A smart pointer implementation inspired by std::shared_ptr. + * + * Features modernized C++11/14/17 syntax, thread-safe reference counting, + * move semantics, and support for custom deleters. + * + * NOTE: Default constructor allocates a new T following legacy behavior. + */ template class SmartPointer { - typedef T element_type; public: + using element_type = T; - explicit - SmartPointer(T* ptr = NULL) : m_counter(0) { - if(!ptr) ptr = new T; + /** + * @brief Constructor from raw pointer. + * If ptr is nullptr, a new T is allocated (legacy behavior). + */ + explicit SmartPointer(T* ptr = nullptr) : m_counter(nullptr) { + if (!ptr) ptr = new T(); if (ptr) m_counter = new ReferenceCounter(ptr); } - // TakeReference // - SmartPointer(T &ref) : m_counter(new ReferenceCounter(&ref,0)) { } - - SmartPointer(const SmartPointer& copy) throw () { - acquire(copy.m_counter); + /** + * @brief Constructor with custom deleter. + */ + template + SmartPointer(T* ptr, D deleter) : m_counter(nullptr) { + if (ptr) m_counter = new ReferenceCounter(ptr, deleter); } - SmartPointer(SmartPointer * copy) throw () { - acquire(copy->m_counter); + /** + * @brief Non-owning constructor from reference. + * Uses a no-op deleter to ensure the referenced object is not destroyed. + */ + SmartPointer(T &ref) : m_counter(new ReferenceCounter(&ref, [](T*){}, 1)) { } + + /** + * @brief Copy constructor. + */ + SmartPointer(const SmartPointer& other) noexcept : m_counter(nullptr) { + acquire(other.m_counter); } - virtual ~SmartPointer() { release(); } + /** + * @brief Copy constructor from a pointer to SmartPointer (Legacy support). + */ + SmartPointer(const SmartPointer* other) noexcept : m_counter(nullptr) { + if (other) acquire(other->m_counter); + } - SmartPointer & operator=(const SmartPointer& copy) { - if (this != ©) - { + /** + * @brief Move constructor. + */ + SmartPointer(SmartPointer&& other) noexcept : m_counter(other.m_counter) { + other.m_counter = nullptr; + } + + /** + * @brief Virtual destructor. + */ + virtual ~SmartPointer() { release(); } + + /** + * @brief Copy assignment. + */ + SmartPointer& operator=(const SmartPointer& other) noexcept { + if (this != &other) { release(); - acquire(copy.m_counter); + acquire(other.m_counter); } return *this; } - T & operator*() const throw () { return *m_counter->ptr; } - T * operator->() const throw () { return m_counter->ptr; } - - T * get() const throw () { - return m_counter ? m_counter->ptr : 0; } - bool unique() const throw () { - return (m_counter ? m_counter->count == 1 : true); } - - - private: - - struct ReferenceCounter - { - ReferenceCounter(T* ptr = 0, unsigned c = 1) : ptr(ptr), count(c) { } - T* ptr; - unsigned count; - } * m_counter; - - // increment the count - void acquire(ReferenceCounter* c) throw () - { - m_counter = c; - if (c && c->count>0) ++c->count; + /** + * @brief Move assignment. + */ + SmartPointer& operator=(SmartPointer&& other) noexcept { + if (this != &other) { + release(); + m_counter = other.m_counter; + other.m_counter = nullptr; + } + return *this; } - // decrement the count, delete if it is 0 - void release() { - if (m_counter) { - if (--m_counter->count == 0) { - delete m_counter->ptr; - } - if (m_counter->count <= 0) { - delete m_counter; - m_counter = NULL; - } + /** + * @brief Resets the smart pointer to hold a new raw pointer. + */ + void reset(T* ptr = nullptr) { + release(); + if (ptr) m_counter = new ReferenceCounter(ptr); + } + + /** + * @brief Resets the smart pointer with a custom deleter. + */ + template + void reset(T* ptr, D deleter) { + release(); + if (ptr) m_counter = new ReferenceCounter(ptr, deleter); + } + + /** + * @brief Swaps contents with another SmartPointer. + */ + void swap(SmartPointer& other) noexcept { + std::swap(m_counter, other.m_counter); + } + + /** + * @brief Dereference operator. + */ + T& operator*() const noexcept { return *m_counter->ptr; } + + /** + * @brief Member access operator. + */ + T* operator->() const noexcept { return m_counter->ptr; } + + /** + * @brief Returns the raw pointer. + */ + T* get() const noexcept { return m_counter ? m_counter->ptr : nullptr; } + + /** + * @brief Returns the number of SmartPointers sharing ownership. + */ + uint32_t use_count() const noexcept { + return m_counter ? m_counter->count.load(std::memory_order_relaxed) : 0; + } + + /** + * @brief Returns true if this is the only SmartPointer owning the resource. + */ + bool unique() const noexcept { return use_count() == 1; } + + /** + * @brief Boolean conversion operator. + */ + explicit operator bool() const noexcept { return get() != nullptr; } + +private: + struct ReferenceCounter { + T* ptr; + std::atomic count; + std::function deleter; + + ReferenceCounter(T* p, uint32_t initial_count = 1) + : ptr(p), count(initial_count), deleter([](T* ptr_to_del) { delete ptr_to_del; }) {} + + template + ReferenceCounter(T* p, D d, uint32_t initial_count = 1) + : ptr(p), count(initial_count), deleter(d) {} + }; + + ReferenceCounter* m_counter; + + void acquire(ReferenceCounter* c) noexcept { + m_counter = c; + if (c) { + c->count.fetch_add(1, std::memory_order_relaxed); } } + void release() noexcept { + if (m_counter) { + if (m_counter->count.fetch_sub(1, std::memory_order_acq_rel) == 1) { + if (m_counter->ptr) { + m_counter->deleter(m_counter->ptr); + } + delete m_counter; + } + m_counter = nullptr; + } + } }; - - +/** + * @brief Global swap for SmartPointer. + */ +template +void swap(SmartPointer& a, SmartPointer& b) noexcept { + a.swap(b); } -#endif // SMARTPOINTER_H +/** + * @brief Equality comparison. + */ +template +bool operator==(const SmartPointer& a, const SmartPointer& b) noexcept { + return a.get() == b.get(); +} + +/** + * @brief Inequality comparison. + */ +template +bool operator!=(const SmartPointer& a, const SmartPointer& b) noexcept { + return a.get() != b.get(); +} + +/** + * @brief Comparison with nullptr. + */ +template +bool operator==(const SmartPointer& a, std::nullptr_t) noexcept { + return a.get() == nullptr; +} + +template +bool operator==(std::nullptr_t, const SmartPointer& a) noexcept { + return a.get() == nullptr; +} + +template +bool operator!=(const SmartPointer& a, std::nullptr_t) noexcept { + return a.get() != nullptr; +} + +template +bool operator!=(std::nullptr_t, const SmartPointer& a) noexcept { + return a.get() != nullptr; +} + +} // namespace uLib + +#endif // U_CORE_SMARTPOINTER_H diff --git a/src/Core/Types.h b/src/Core/Types.h index d486480..1ea47ec 100644 --- a/src/Core/Types.h +++ b/src/Core/Types.h @@ -139,7 +139,6 @@ typedef id_t Id_t; typedef void *Pointer_t; typedef bool Bool_t; // Boolean (0=false, 1=true) (bool) - //--- bit manipulation --------------------------------------------------------- #ifndef BIT #define BIT(n) (1ULL << (n)) @@ -182,7 +181,7 @@ typedef bool Bool_t; // Boolean (0=false, 1=true) (bool) \ public: \ typedef type_info::BaseClass BaseClass; \ - virtual const char *type_name() const override { return type_info::name; } \ + virtual const char *type_name() const override { return type_info::name; } \ /**/ /** diff --git a/src/Core/testing/CMakeLists.txt b/src/Core/testing/CMakeLists.txt index 75ae59a..73766f6 100644 --- a/src/Core/testing/CMakeLists.txt +++ b/src/Core/testing/CMakeLists.txt @@ -2,6 +2,7 @@ # TESTS set( TESTS SmartVectorTest + SmartPointerTest VectorTest ObjectFlagsTest ObjectParametersTest