#pragma once /** * @file object_pool.h * @brief 高性能对象池 + 写时复制 * * 对象池:预分配 chunk,free-list 回收,O(1) acquire/release。 * 写时复制:引用计数共享,修改时深拷贝,避免不必要的大对象拷贝。 * * @ingroup foundation */ #include #include #include #include #include #include #include namespace vde::core { // ═══════════════════════════════════════════════════════════ // ObjectPool — 单线程对象池 // ═══════════════════════════════════════════════════════════ /** * @brief 高性能对象池(单线程) * * 预分配 chunk 减少 malloc 调用,free-list 实现 O(1) 回收。 * * @tparam T 池化对象类型(需有默认构造函数) * @tparam ChunkSize 每次扩容时分配的 chunk 大小 * * @ingroup foundation */ template class ObjectPool { static_assert(std::is_default_constructible_v, "T must be default constructible"); public: ObjectPool() { expand(); } ~ObjectPool() { for (auto* chunk : chunks_) { ::operator delete(chunk); } } /// 禁止拷贝 ObjectPool(const ObjectPool&) = delete; ObjectPool& operator=(const ObjectPool&) = delete; /** * @brief 获取一个对象(复用或新建) * @return 对象指针 */ [[nodiscard]] T* acquire(); /** * @brief 归还对象到池中 * @param ptr 之前由 acquire() 返回的指针 */ void release(T* ptr); /// 统计 [[nodiscard]] size_t total_allocated() const { return total_allocated_; } [[nodiscard]] size_t total_reused() const { return total_reused_; } [[nodiscard]] size_t pool_size() const { return chunks_.size() * ChunkSize; } [[nodiscard]] size_t free_count() const { return free_count_; } [[nodiscard]] double reuse_rate() const; private: struct Node { Node* next = nullptr; T data; }; std::vector chunks_; ///< 分配的 chunk Node* free_list_ = nullptr; ///< 空闲列表头 size_t free_count_ = 0; size_t total_allocated_ = 0; size_t total_reused_ = 0; void expand(); }; template T* ObjectPool::acquire() { if (free_list_ == nullptr) { expand(); } total_allocated_++; if (free_list_ != chunks_.back()) { total_reused_++; } Node* node = free_list_; free_list_ = node->next; free_count_--; // Reset the object to default state node->data = T{}; return &node->data; } template void ObjectPool::release(T* ptr) { if (!ptr) return; // Recover the Node pointer from the data pointer Node* node = reinterpret_cast( reinterpret_cast(ptr) - offsetof(Node, data)); node->next = free_list_; free_list_ = node; free_count_++; } template void ObjectPool::expand() { auto* chunk = static_cast(::operator new(ChunkSize * sizeof(Node))); chunks_.push_back(chunk); // Build free list from the new chunk for (size_t i = 0; i < ChunkSize; ++i) { chunk[i].next = free_list_; free_list_ = &chunk[i]; } free_count_ += ChunkSize; } template double ObjectPool::reuse_rate() const { if (total_allocated_ == 0) return 0.0; return static_cast(total_reused_) / total_allocated_; } // ═══════════════════════════════════════════════════════════ // ThreadSafeObjectPool — 线程安全对象池 // ═══════════════════════════════════════════════════════════ /** * @brief 线程安全对象池 * * 每线程独立 pool + global fallback,无锁竞争。 * * @tparam T 池化对象类型 * @tparam ChunkSize 每个线程 local pool 的 chunk 大小 */ template class ThreadSafeObjectPool { public: [[nodiscard]] T* acquire(); void release(T* ptr); [[nodiscard]] size_t total_allocated() const { return global_allocated_.load(); } private: // Per-thread pool (thread_local) static thread_local ObjectPool local_pool_; // Fallback when local pool is empty ObjectPool global_pool_; std::mutex global_mutex_; std::atomic global_allocated_{0}; }; template thread_local ObjectPool ThreadSafeObjectPool::local_pool_{}; template T* ThreadSafeObjectPool::acquire() { // Try local pool first (no lock) if (local_pool_.free_count() > 0) { return local_pool_.acquire(); } // Fall back to global pool std::lock_guard lock(global_mutex_); if (global_pool_.free_count() > 0) { global_allocated_++; return global_pool_.acquire(); } // Both empty — expand global global_allocated_++; return global_pool_.acquire(); } template void ThreadSafeObjectPool::release(T* ptr) { // Return to local pool local_pool_.release(ptr); } // ═══════════════════════════════════════════════════════════ // CowPtr — Copy-on-Write 智能指针 // ═══════════════════════════════════════════════════════════ /** * @brief 写时复制 (Copy-on-Write) 智能指针 * * 类似 shared_ptr,但修改时自动深拷贝(detach)。 * 用于大对象如 NurbsSurface、HalfedgeMesh 的共享。 * * @tparam T 被包装类型 */ template class CowPtr { public: CowPtr() = default; explicit CowPtr(T value) : data_(std::make_shared(std::move(value))) {} CowPtr(const CowPtr& other) = default; CowPtr& operator=(const CowPtr& other) = default; CowPtr(CowPtr&&) = default; CowPtr& operator=(CowPtr&&) = default; /// 只读访问 [[nodiscard]] const T& read() const { ensure_valid(); return *data_; } /// 可写访问(如有共享则深拷贝) [[nodiscard]] T& write() { ensure_valid(); detach(); return *data_; } /// 只读解引用 [[nodiscard]] const T& operator*() const { return read(); } [[nodiscard]] const T* operator->() const { return &read(); } /// 引用计数 [[nodiscard]] long use_count() const { return data_ ? data_.use_count() : 0; } /// 是否唯一持有 [[nodiscard]] bool unique() const { return data_ && data_.use_count() == 1; } /// 浅拷贝(共享数据) [[nodiscard]] CowPtr shallow_copy() const { return CowPtr(*this); } /// 深拷贝(显式复制数据) [[nodiscard]] CowPtr deep_copy() const { if (!data_) return CowPtr(); return CowPtr(T(*data_)); } private: std::shared_ptr data_; void ensure_valid() const { if (!data_) { const_cast(this)->data_ = std::make_shared(); } } /// 如果数据被共享,则深拷贝 void detach() { if (data_ && data_.use_count() > 1) { data_ = std::make_shared(*data_); } } }; } // namespace vde::core