diff --git a/src/reference.hpp b/src/reference.hpp index 7a191e8..a12a223 100644 --- a/src/reference.hpp +++ b/src/reference.hpp @@ -24,7 +24,8 @@ struct ControlBlock { std::atomic weak_count; ControlBlock() - : strong_count(1), weak_count(0) {} // Start with 1 strong reference + : strong_count(1), weak_count(1) { + } // Start with 1 strong, 1 weak (biased) /** * @brief Increment strong reference count @@ -64,31 +65,22 @@ template struct Ref { /** * @brief Get raw pointer to managed object */ - T *get() const { - if (!control_block) - return nullptr; - constexpr size_t cb_size = sizeof(detail::ControlBlock); - constexpr size_t alignment = alignof(T); - constexpr size_t padded_cb_size = - (cb_size + alignment - 1) & ~(alignment - 1); - return reinterpret_cast(reinterpret_cast(control_block) + - padded_cb_size); - } + T *get() const noexcept { return ptr; } /** * @brief Dereference operator */ - T &operator*() const { return *get(); } + T &operator*() const { return *ptr; } /** * @brief Arrow operator */ - T *operator->() const { return get(); } + T *operator->() const { return ptr; } /** * @brief Check if Ref is valid (not empty) */ - explicit operator bool() const noexcept { return control_block != nullptr; } + explicit operator bool() const noexcept { return ptr != nullptr; } /** * @brief Destructor - decrements strong reference count @@ -98,7 +90,8 @@ template struct Ref { /** * @brief Copy constructor - increments strong reference count */ - Ref(const Ref &other) noexcept : control_block(other.control_block) { + Ref(const Ref &other) noexcept + : ptr(other.ptr), control_block(other.control_block) { if (control_block) { control_block->increment_strong(); } @@ -110,6 +103,7 @@ template struct Ref { Ref &operator=(const Ref &other) noexcept { if (this != &other) { release(); + ptr = other.ptr; control_block = other.control_block; if (control_block) { control_block->increment_strong(); @@ -121,7 +115,9 @@ template struct Ref { /** * @brief Move constructor - transfers ownership */ - Ref(Ref &&other) noexcept : control_block(other.control_block) { + Ref(Ref &&other) noexcept + : ptr(other.ptr), control_block(other.control_block) { + other.ptr = nullptr; other.control_block = nullptr; } @@ -131,7 +127,9 @@ template struct Ref { Ref &operator=(Ref &&other) noexcept { if (this != &other) { release(); + ptr = other.ptr; control_block = other.control_block; + other.ptr = nullptr; other.control_block = nullptr; } return *this; @@ -142,6 +140,7 @@ template struct Ref { */ void reset() noexcept { release(); + ptr = nullptr; control_block = nullptr; } @@ -160,11 +159,13 @@ template struct Ref { /** * @brief Default constructor - creates empty Ref */ - Ref() : control_block(nullptr) {} + Ref() : ptr(nullptr), control_block(nullptr) {} private: - explicit Ref(detail::ControlBlock *cb) : control_block(cb) {} + explicit Ref(T *object_ptr, detail::ControlBlock *cb) + : ptr(object_ptr), control_block(cb) {} + T *ptr; detail::ControlBlock *control_block; /** @@ -172,24 +173,19 @@ private: */ void release() noexcept { if (control_block) { - // Prevent weak count from going to 0 concurrently - control_block->increment_weak(); - uint32_t prev_strong = control_block->decrement_strong(); // If this was the last strong reference, destroy the object if (prev_strong == 1) { - T *obj = get(); - obj->~T(); - } + ptr->~T(); - // Now release our temporary weak reference - uint32_t prev_weak = control_block->decrement_weak(); + // Release the bias - decrement weak count for strong references + uint32_t prev_weak = control_block->decrement_weak(); - // If this was the last weak reference and we destroyed the object, - // we can free the control block - if (prev_weak == 1 && prev_strong == 1) { - std::free(control_block); + // If weak count hits 0, free control block + if (prev_weak == 1) { + std::free(control_block); + } } } } @@ -219,7 +215,7 @@ template struct WeakRef { expected_strong, expected_strong + 1, std::memory_order_acquire, std::memory_order_relaxed)) { // Success - we incremented the strong count - return Ref(control_block); + return Ref(get_object_ptr(), control_block); } // CAS failed, expected_strong now contains the current value, retry } @@ -314,18 +310,27 @@ private: detail::ControlBlock *control_block; + // Helper to calculate object pointer from control block + T *get_object_ptr() const { + if (!control_block) + return nullptr; + constexpr size_t cb_size = sizeof(detail::ControlBlock); + constexpr size_t alignment = alignof(T); + constexpr size_t padded_cb_size = + (cb_size + alignment - 1) & ~(alignment - 1); + return reinterpret_cast(reinterpret_cast(control_block) + + padded_cb_size); + } + /** * @brief Release current weak reference and handle cleanup */ void release() noexcept { if (control_block) { - // Prevent strong count from going to 0 concurrently - auto strong = lock(); uint32_t prev_weak = control_block->decrement_weak(); - // If this was the last weak reference, check if we need to free control - // block - if (prev_weak == 1 && !strong) { + // If weak count hits 0, free control block + if (prev_weak == 1) { std::free(control_block); } } @@ -357,6 +362,6 @@ template Ref make_ref(Args &&...args) { } auto *cb = new (buf) detail::ControlBlock(); - new (buf + padded_cb_size) T{std::forward(args)...}; - return Ref(cb); + T *obj = new (buf + padded_cb_size) T{std::forward(args)...}; + return Ref(obj, cb); }