diff --git a/src/reference.hpp b/src/reference.hpp index c41690e..62129bd 100644 --- a/src/reference.hpp +++ b/src/reference.hpp @@ -103,7 +103,10 @@ struct ControlBlock { } // namespace detail template struct Ref { - T *get() { + /** + * @brief Get raw pointer to managed object + */ + T *get() const { if (!control_block) return nullptr; constexpr size_t cb_size = sizeof(detail::ControlBlock); @@ -114,12 +117,120 @@ template struct Ref { padded_cb_size); } -private: - explicit Ref(detail::ControlBlock *cb) : control_block(cb) {} + /** + * @brief Dereference operator + */ + T &operator*() const { return *get(); } + + /** + * @brief Arrow operator + */ + T *operator->() const { return get(); } + + /** + * @brief Check if Ref is valid (not empty) + */ + explicit operator bool() const noexcept { return control_block != nullptr; } + + /** + * @brief Destructor - decrements strong reference count + */ + ~Ref() { release(); } + + /** + * @brief Copy constructor - increments strong reference count + */ + Ref(const Ref &other) noexcept : control_block(other.control_block) { + if (control_block) { + control_block->increment_strong(); + } + } + + /** + * @brief Copy assignment operator + */ + Ref &operator=(const Ref &other) noexcept { + if (this != &other) { + release(); + control_block = other.control_block; + if (control_block) { + control_block->increment_strong(); + } + } + return *this; + } + + /** + * @brief Move constructor - transfers ownership + */ + Ref(Ref &&other) noexcept : control_block(other.control_block) { + other.control_block = nullptr; + } + + /** + * @brief Move assignment operator + */ + Ref &operator=(Ref &&other) noexcept { + if (this != &other) { + release(); + control_block = other.control_block; + other.control_block = nullptr; + } + return *this; + } + + /** + * @brief Reset to empty state + */ + void reset() noexcept { + release(); + control_block = nullptr; + } + + /** + * @brief Equality comparison + */ + bool operator==(const Ref &other) const noexcept { + return control_block == other.control_block; + } + + /** + * @brief Inequality comparison + */ + bool operator!=(const Ref &other) const noexcept { return !(*this == other); } + + /** + * @brief Default constructor - creates empty Ref + */ Ref() : control_block(nullptr) {} +private: + explicit Ref(detail::ControlBlock *cb) : control_block(cb) {} + detail::ControlBlock *control_block; + /** + * @brief Release current reference and handle cleanup + */ + void release() noexcept { + if (control_block) { + uint64_t prev = control_block->decrement_strong(); + uint32_t prev_strong = static_cast(prev); + + // If this was the last strong reference, destroy the object + if (prev_strong == 1) { + T *obj = get(); + obj->~T(); + + // If no weak references either, free the entire allocation + uint32_t prev_weak = static_cast(prev >> 32); + if (prev_weak == 0) { + std::free(control_block); + } + } + } + } + template friend Ref make_ref(Args &&...args); @@ -127,6 +238,10 @@ private: }; template struct WeakRef { + /** + * @brief Attempt to promote WeakRef to Ref + * @return Valid Ref if object still alive, empty Ref otherwise + */ Ref lock() { if (!control_block) { return Ref(); @@ -155,12 +270,109 @@ template struct WeakRef { return Ref(control_block); } -private: - explicit WeakRef(detail::ControlBlock *cb) : control_block(cb) {} + /** + * @brief Destructor - decrements weak reference count + */ + ~WeakRef() { release(); } + + /** + * @brief Copy constructor from WeakRef + */ + WeakRef(const WeakRef &other) noexcept : control_block(other.control_block) { + if (control_block) { + control_block->increment_weak(); + } + } + + /** + * @brief Copy constructor from Ref + */ + WeakRef(const Ref &ref) noexcept : control_block(ref.control_block) { + if (control_block) { + control_block->increment_weak(); + } + } + + /** + * @brief Copy assignment from WeakRef + */ + WeakRef &operator=(const WeakRef &other) noexcept { + if (this != &other) { + release(); + control_block = other.control_block; + if (control_block) { + control_block->increment_weak(); + } + } + return *this; + } + + /** + * @brief Copy assignment from Ref + */ + WeakRef &operator=(const Ref &ref) noexcept { + release(); + control_block = ref.control_block; + if (control_block) { + control_block->increment_weak(); + } + return *this; + } + + /** + * @brief Move constructor + */ + WeakRef(WeakRef &&other) noexcept : control_block(other.control_block) { + other.control_block = nullptr; + } + + /** + * @brief Move assignment + */ + WeakRef &operator=(WeakRef &&other) noexcept { + if (this != &other) { + release(); + control_block = other.control_block; + other.control_block = nullptr; + } + return *this; + } + + /** + * @brief Reset to empty state + */ + void reset() noexcept { + release(); + control_block = nullptr; + } + + /** + * @brief Default constructor - creates empty WeakRef + */ WeakRef() : control_block(nullptr) {} +private: + explicit WeakRef(detail::ControlBlock *cb) : control_block(cb) {} + detail::ControlBlock *control_block; + /** + * @brief Release current weak reference and handle cleanup + */ + void release() noexcept { + if (control_block) { + uint64_t prev = control_block->decrement_weak(); + uint32_t prev_strong = static_cast(prev); + uint32_t prev_weak = static_cast(prev >> 32); + + // If this was the last weak reference and no strong references, free + // control block + if (prev_weak == 1 && prev_strong == 0) { + std::free(control_block); + } + } + } + template friend struct Ref; };