Used biased weak count, cache T* pointer
Logically, the strong pointer that destroys T owns +1 weak count too
This commit is contained in:
@@ -24,7 +24,8 @@ struct ControlBlock {
|
|||||||
std::atomic<uint32_t> weak_count;
|
std::atomic<uint32_t> weak_count;
|
||||||
|
|
||||||
ControlBlock()
|
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
|
* @brief Increment strong reference count
|
||||||
@@ -64,31 +65,22 @@ template <typename T> struct Ref {
|
|||||||
/**
|
/**
|
||||||
* @brief Get raw pointer to managed object
|
* @brief Get raw pointer to managed object
|
||||||
*/
|
*/
|
||||||
T *get() const {
|
T *get() const noexcept { return ptr; }
|
||||||
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<T *>(reinterpret_cast<char *>(control_block) +
|
|
||||||
padded_cb_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Dereference operator
|
* @brief Dereference operator
|
||||||
*/
|
*/
|
||||||
T &operator*() const { return *get(); }
|
T &operator*() const { return *ptr; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Arrow operator
|
* @brief Arrow operator
|
||||||
*/
|
*/
|
||||||
T *operator->() const { return get(); }
|
T *operator->() const { return ptr; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Check if Ref is valid (not empty)
|
* @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
|
* @brief Destructor - decrements strong reference count
|
||||||
@@ -98,7 +90,8 @@ template <typename T> struct Ref {
|
|||||||
/**
|
/**
|
||||||
* @brief Copy constructor - increments strong reference count
|
* @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) {
|
if (control_block) {
|
||||||
control_block->increment_strong();
|
control_block->increment_strong();
|
||||||
}
|
}
|
||||||
@@ -110,6 +103,7 @@ template <typename T> struct Ref {
|
|||||||
Ref &operator=(const Ref &other) noexcept {
|
Ref &operator=(const Ref &other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
release();
|
release();
|
||||||
|
ptr = other.ptr;
|
||||||
control_block = other.control_block;
|
control_block = other.control_block;
|
||||||
if (control_block) {
|
if (control_block) {
|
||||||
control_block->increment_strong();
|
control_block->increment_strong();
|
||||||
@@ -121,7 +115,9 @@ template <typename T> struct Ref {
|
|||||||
/**
|
/**
|
||||||
* @brief Move constructor - transfers ownership
|
* @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;
|
other.control_block = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +127,9 @@ template <typename T> struct Ref {
|
|||||||
Ref &operator=(Ref &&other) noexcept {
|
Ref &operator=(Ref &&other) noexcept {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
release();
|
release();
|
||||||
|
ptr = other.ptr;
|
||||||
control_block = other.control_block;
|
control_block = other.control_block;
|
||||||
|
other.ptr = nullptr;
|
||||||
other.control_block = nullptr;
|
other.control_block = nullptr;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -142,6 +140,7 @@ template <typename T> struct Ref {
|
|||||||
*/
|
*/
|
||||||
void reset() noexcept {
|
void reset() noexcept {
|
||||||
release();
|
release();
|
||||||
|
ptr = nullptr;
|
||||||
control_block = nullptr;
|
control_block = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,11 +159,13 @@ template <typename T> struct Ref {
|
|||||||
/**
|
/**
|
||||||
* @brief Default constructor - creates empty Ref
|
* @brief Default constructor - creates empty Ref
|
||||||
*/
|
*/
|
||||||
Ref() : control_block(nullptr) {}
|
Ref() : ptr(nullptr), control_block(nullptr) {}
|
||||||
|
|
||||||
private:
|
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;
|
detail::ControlBlock *control_block;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,27 +173,22 @@ private:
|
|||||||
*/
|
*/
|
||||||
void release() noexcept {
|
void release() noexcept {
|
||||||
if (control_block) {
|
if (control_block) {
|
||||||
// Prevent weak count from going to 0 concurrently
|
|
||||||
control_block->increment_weak();
|
|
||||||
|
|
||||||
uint32_t prev_strong = control_block->decrement_strong();
|
uint32_t prev_strong = control_block->decrement_strong();
|
||||||
|
|
||||||
// If this was the last strong reference, destroy the object
|
// If this was the last strong reference, destroy the object
|
||||||
if (prev_strong == 1) {
|
if (prev_strong == 1) {
|
||||||
T *obj = get();
|
ptr->~T();
|
||||||
obj->~T();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now release our temporary weak reference
|
// Release the bias - decrement weak count for strong references
|
||||||
uint32_t prev_weak = control_block->decrement_weak();
|
uint32_t prev_weak = control_block->decrement_weak();
|
||||||
|
|
||||||
// If this was the last weak reference and we destroyed the object,
|
// If weak count hits 0, free control block
|
||||||
// we can free the control block
|
if (prev_weak == 1) {
|
||||||
if (prev_weak == 1 && prev_strong == 1) {
|
|
||||||
std::free(control_block);
|
std::free(control_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename U, typename... Args>
|
template <typename U, typename... Args>
|
||||||
friend Ref<U> make_ref(Args &&...args);
|
friend Ref<U> make_ref(Args &&...args);
|
||||||
@@ -219,7 +215,7 @@ template <typename T> struct WeakRef {
|
|||||||
expected_strong, expected_strong + 1, std::memory_order_acquire,
|
expected_strong, expected_strong + 1, std::memory_order_acquire,
|
||||||
std::memory_order_relaxed)) {
|
std::memory_order_relaxed)) {
|
||||||
// Success - we incremented the strong count
|
// Success - we incremented the strong count
|
||||||
return Ref<T>(control_block);
|
return Ref<T>(get_object_ptr(), control_block);
|
||||||
}
|
}
|
||||||
// CAS failed, expected_strong now contains the current value, retry
|
// CAS failed, expected_strong now contains the current value, retry
|
||||||
}
|
}
|
||||||
@@ -314,18 +310,27 @@ private:
|
|||||||
|
|
||||||
detail::ControlBlock *control_block;
|
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<T *>(reinterpret_cast<char *>(control_block) +
|
||||||
|
padded_cb_size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Release current weak reference and handle cleanup
|
* @brief Release current weak reference and handle cleanup
|
||||||
*/
|
*/
|
||||||
void release() noexcept {
|
void release() noexcept {
|
||||||
if (control_block) {
|
if (control_block) {
|
||||||
// Prevent strong count from going to 0 concurrently
|
|
||||||
auto strong = lock();
|
|
||||||
uint32_t prev_weak = control_block->decrement_weak();
|
uint32_t prev_weak = control_block->decrement_weak();
|
||||||
|
|
||||||
// If this was the last weak reference, check if we need to free control
|
// If weak count hits 0, free control block
|
||||||
// block
|
if (prev_weak == 1) {
|
||||||
if (prev_weak == 1 && !strong) {
|
|
||||||
std::free(control_block);
|
std::free(control_block);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,6 +362,6 @@ template <typename T, typename... Args> Ref<T> make_ref(Args &&...args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto *cb = new (buf) detail::ControlBlock();
|
auto *cb = new (buf) detail::ControlBlock();
|
||||||
new (buf + padded_cb_size) T{std::forward<Args>(args)...};
|
T *obj = new (buf + padded_cb_size) T{std::forward<Args>(args)...};
|
||||||
return Ref<T>(cb);
|
return Ref<T>(obj, cb);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user