Require explicit copies for Ref/WeakRef
This commit is contained in:
@@ -22,8 +22,8 @@
|
||||
* Basic usage:
|
||||
* @code
|
||||
* auto obj = make_ref<MyClass>(args...); // Create managed object
|
||||
* auto copy = obj; // Copy (thread-safe)
|
||||
* WeakRef<MyClass> weak = obj; // Create weak reference
|
||||
* auto copy = obj.copy(); // Explicit copy (thread-safe)
|
||||
* WeakRef<MyClass> weak = obj.as_weak(); // Create weak reference
|
||||
* auto locked = weak.lock(); // Try to promote to strong
|
||||
* @endcode
|
||||
*
|
||||
@@ -31,6 +31,9 @@
|
||||
* safely copy, move, and destroy references to the same object.
|
||||
*/
|
||||
|
||||
// Forward declaration
|
||||
template <typename T> struct WeakRef;
|
||||
|
||||
namespace detail {
|
||||
struct ControlBlock {
|
||||
std::atomic<uint32_t> strong_count;
|
||||
@@ -126,57 +129,28 @@ template <typename T> struct Ref {
|
||||
~Ref() { release(); }
|
||||
|
||||
/**
|
||||
* @brief Copy constructor - increments strong reference count
|
||||
* @brief Copy constructor - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
Ref(const Ref &other) noexcept
|
||||
: ptr(other.ptr), control_block(other.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_strong();
|
||||
}
|
||||
}
|
||||
Ref(const Ref &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting copy constructor for polymorphism (Derived -> Base)
|
||||
* @brief Converting copy constructor - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
Ref(const Ref<U> &other) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
: ptr(other.ptr), control_block(other.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_strong();
|
||||
}
|
||||
}
|
||||
template <typename U> Ref(const Ref<U> &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment operator
|
||||
* @brief Copy assignment operator - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Ref &operator=(const Ref &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting assignment operator for polymorphism (Derived -> Base)
|
||||
* @brief Converting assignment operator - deleted to prevent accidental
|
||||
* copies Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
Ref &operator=(const Ref<U> &other) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
{
|
||||
release();
|
||||
ptr = other.ptr;
|
||||
control_block = other.control_block;
|
||||
if (control_block) {
|
||||
control_block->increment_strong();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename U> Ref &operator=(const Ref<U> &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor - transfers ownership
|
||||
@@ -228,6 +202,28 @@ template <typename T> struct Ref {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explicitly create a copy with shared ownership
|
||||
* @return New Ref that shares ownership of the same object
|
||||
*/
|
||||
[[nodiscard]] Ref copy() const noexcept {
|
||||
if (control_block) {
|
||||
control_block->increment_strong();
|
||||
}
|
||||
return Ref(ptr, control_block);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a WeakRef that observes this object
|
||||
* @return New WeakRef that observes the same object
|
||||
*/
|
||||
[[nodiscard]] WeakRef<T> as_weak() const noexcept {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
return WeakRef<T>(control_block);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset to empty state
|
||||
*/
|
||||
@@ -347,76 +343,40 @@ template <typename T> struct WeakRef {
|
||||
~WeakRef() { release(); }
|
||||
|
||||
/**
|
||||
* @brief Copy constructor from WeakRef
|
||||
* @brief Copy constructor from WeakRef - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
WeakRef(const WeakRef &other) noexcept : control_block(other.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
}
|
||||
WeakRef(const WeakRef &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Copy constructor from Ref
|
||||
* @brief Copy constructor from Ref - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
WeakRef(const Ref<T> &ref) noexcept : control_block(ref.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
}
|
||||
WeakRef(const Ref<T> &ref) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting copy constructor from WeakRef for polymorphism
|
||||
* @brief Converting copy constructor from WeakRef - deleted to prevent
|
||||
* accidental copies Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
WeakRef(const WeakRef<U> &other) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
: control_block(other.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
}
|
||||
template <typename U> WeakRef(const WeakRef<U> &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting copy constructor from Ref for polymorphism
|
||||
* @brief Converting copy constructor from Ref - deleted to prevent accidental
|
||||
* copies Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
WeakRef(const Ref<U> &ref) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
: control_block(ref.control_block) {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
}
|
||||
template <typename U> WeakRef(const Ref<U> &ref) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting copy assignment from WeakRef for polymorphism
|
||||
* @brief Converting copy assignment from WeakRef - deleted to prevent
|
||||
* accidental copies Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
WeakRef &operator=(const WeakRef<U> &other) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
{
|
||||
release();
|
||||
control_block = other.control_block;
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename U> WeakRef &operator=(const WeakRef<U> &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting copy assignment from Ref for polymorphism
|
||||
* @brief Converting copy assignment from Ref - deleted to prevent accidental
|
||||
* copies Use copy() method for explicit copying
|
||||
*/
|
||||
template <typename U>
|
||||
WeakRef &operator=(const Ref<U> &ref) noexcept
|
||||
requires std::is_convertible_v<U *, T *>
|
||||
{
|
||||
release();
|
||||
control_block = ref.control_block;
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
template <typename U> WeakRef &operator=(const Ref<U> &ref) = delete;
|
||||
|
||||
/**
|
||||
* @brief Converting move constructor from WeakRef for polymorphism
|
||||
@@ -442,30 +402,16 @@ template <typename T> struct WeakRef {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Copy assignment from WeakRef
|
||||
* @brief Copy assignment from WeakRef - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
WeakRef &operator=(const WeakRef &other) noexcept {
|
||||
if (this != &other) {
|
||||
release();
|
||||
control_block = other.control_block;
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
WeakRef &operator=(const WeakRef &other) = delete;
|
||||
|
||||
/**
|
||||
* @brief Copy assignment from Ref
|
||||
* @brief Copy assignment from Ref - deleted to prevent accidental copies
|
||||
* Use copy() method for explicit copying
|
||||
*/
|
||||
WeakRef &operator=(const Ref<T> &ref) noexcept {
|
||||
release();
|
||||
control_block = ref.control_block;
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
WeakRef &operator=(const Ref<T> &ref) = delete;
|
||||
|
||||
/**
|
||||
* @brief Move constructor
|
||||
@@ -486,6 +432,17 @@ template <typename T> struct WeakRef {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Explicitly create a copy with shared weak reference
|
||||
* @return New WeakRef that observes the same object
|
||||
*/
|
||||
[[nodiscard]] WeakRef copy() const noexcept {
|
||||
if (control_block) {
|
||||
control_block->increment_weak();
|
||||
}
|
||||
return WeakRef(control_block);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset to empty state
|
||||
*/
|
||||
@@ -550,6 +507,8 @@ private:
|
||||
* @code
|
||||
* auto obj = make_ref<MyClass>(arg1, arg2);
|
||||
* auto empty_vec = make_ref<std::vector<int>>();
|
||||
* auto obj_copy = obj.copy(); // Explicit copy
|
||||
* WeakRef<MyClass> weak = obj.as_weak(); // Create weak reference
|
||||
* @endcode
|
||||
*
|
||||
* Thread safety: Safe to call from multiple threads simultaneously.
|
||||
|
||||
@@ -25,7 +25,7 @@ Ref<Server> Server::create(const weaseldb::Config &config,
|
||||
ConnectionHandler &handler,
|
||||
const std::vector<int> &listen_fds) {
|
||||
auto result = make_ref<Server>(config, handler, listen_fds);
|
||||
result->self_ = result;
|
||||
result->self_ = result.as_weak();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ int Server::create_local_connection() {
|
||||
// Create Connection object
|
||||
auto connection = std::unique_ptr<Connection>(new Connection(
|
||||
addr, server_fd, connection_id_.fetch_add(1, std::memory_order_relaxed),
|
||||
epoll_index, &handler_, self_));
|
||||
epoll_index, &handler_, self_.copy()));
|
||||
|
||||
// Store in registry
|
||||
connection_registry_.store(server_fd, std::move(connection));
|
||||
@@ -422,7 +422,7 @@ void Server::start_io_threads(std::vector<std::thread> &threads) {
|
||||
batch[batch_count] = std::unique_ptr<Connection>(new Connection(
|
||||
addr, fd,
|
||||
connection_id_.fetch_add(1, std::memory_order_relaxed),
|
||||
epoll_index, &handler_, self_));
|
||||
epoll_index, &handler_, self_.copy()));
|
||||
batch_events[batch_count] =
|
||||
EPOLLIN; // New connections always start with read
|
||||
batch_count++;
|
||||
|
||||
Reference in New Issue
Block a user