带引用计数器的对象缓存

Objects cache with references counter

本文关键字:对象 缓存 计数器 引用      更新时间:2023-10-16

我想创建一个C++对象工厂,该工厂将通过id创建一些对象。每个对象都必须有一个引用计数器。如果再次请求具有相同 id 的对象,则必须返回相同的对象(如果它仍在内存中)。

虽然有一些东西保留指向对象的指针,但不会删除此对象。当工厂缓存中没有指向对象的指针但指针时,此对象将放置在 QCache 中,如果在一段时间内不再请求它,则会将其删除。

实现这一点的最佳方法是什么?

这是我的做法。

首先,factory类只会保存指向它实例化的对象的观察指针。这样,当不存在对对象的拥有引用时,将立即删除对象,而无需将它们放入队列中。

然后,factory类将返回指向它实例化的对象的共享指针,这些共享指针将指定一个自定义删除器,以便在销毁时从工厂的映射中注销已删除的对象。

假设要实例化的对象有一个接受其 ID 作为参数的构造函数,以及一个get_id()返回其 ID 的函数,下面是工厂类的代码:

#include <memory>
#include <unordered_map>
#include <functional>
using namespace std;
using namespace std::placeholders;
template<typename T>
class factory
{
public:
    shared_ptr<T> get_instance(int id)
    {
        auto i = m_map.find(id);
        if (i == m_map.end())
        {
            return create(id);
        }
        else
        {
            shared_ptr<T> p = i->second.lock();
            if (p == nullptr)
            {
                p = create(id);
            }
            return p;
        }
    }
    shared_ptr<T> create_instance()
    {
        shared_ptr<T> p = create(nextId);
        nextId++;
        return p;
    }
    void unregister(T* p)
    {
        int id = p->get_id();
        m_map.erase(id);
        delete p;
    }
private:
    shared_ptr<T> create(int id)
    {
        shared_ptr<T> p(new T(id), bind(&factory::unregister, this, _1));
        m_map[id] = p;
        return p;
    }
    unordered_map<int, weak_ptr<T>> m_map;
    int nextId = 0;
};

这就是您将如何使用它:

struct A
{
    A(int id) : _id(id) { }
    int get_id() const { return _id; }
    int _id;
};
int main()
{
    factory<A> f;
    {
        shared_ptr<A> pA = f.get_instance(5);
        shared_ptr<A> pB = pA;
        // ...
        // The object with ID 5 will go out of scope and get unregistered
    }
    shared_ptr<A> pA = f.get_instance(3);
    shared_ptr<A> pB = f.get_instance(3); // This will return the existing object
    //
    // Instance with ID 3 will go out of scope and get unregistered
}