Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ObjectPool逻辑可能有问题 #21

Open
vincentbryan opened this issue Apr 3, 2018 · 3 comments
Open

ObjectPool逻辑可能有问题 #21

vincentbryan opened this issue Apr 3, 2018 · 3 comments

Comments

@vincentbryan
Copy link

vincentbryan commented Apr 3, 2018

ObjectPool的Init中:

auto constructName = typeid(Constructor<Args...>).name(); //不区分引用
for (size_t i = 0; i <num; i++){
	m_object_map.emplace(constructName, shared_ptr<T>(new T(std::forward<Args>(args)...), [this, constructName](T* p) //删除器中不直接删除对象,而是回收到对象池中,以供下次使用
			{
				m_object_map.emplace(std::move(constructName), std::shared_ptr<T>(p));
			}));
}

当对象第一次被回收之后重新加入map时没有再次添加删除器,那么第二次删除之后就没有了。但第三次再次获取时就会获得空指针,如:

    ObjectPool<Test> objectPool;
    objectPool.Init(2, 3, 4.5);
    {
        {
            auto t1 = objectPool.Get<int, double>(); t1->print();
            auto t2 = objectPool.Get<int, double>(); t2->print();
        }

        auto t1 = objectPool.Get<int, double>(); t1->print();
        auto t2 = objectPool.Get<int, double>(); t2->print();
    }

    auto t1 = objectPool.Get<int, double>(); t1->print();
    auto t2 = objectPool.Get<int, double>(); t2->print();
@kikyoo
Copy link

kikyoo commented Apr 4, 2018

对象池的使用逻辑或者说流程,应该是(1)对象池初始化,(2)获取对象,(3)回收对象,(4)重复2,3 若干次,(5)对象池销毁或者析构。你所说的第二次删除应该是指(5)。

@ender233
Copy link

@kikyoo
我理解他说的是 (2),再次获取对象的情况。而这种情况下 原代码中确实是没有删除器的。

    template<typename... Args>
    std::shared_ptr<T> Get()
    {
        string constructName = typeid(Constructor<Args...>).name();

        auto range = m_object_map.equal_range(constructName);
        for (auto it = range.first; it != range.second; ++it)
        {
            auto ptr = it->second;
            m_object_map.erase(it);
            return ptr;
        }

获取对象的时候在池中删除,并没有给新的删除器. 所以在第二次取出来的时候已经是个普通的std::shared_ptr<T>,析构后也无法放入池中。

想对照的看SimpleObjectPool.hpp的处理:
每次把对象从池中拿出来,立马注册了一个DeleterType,保证析构后可以放到池子中。

    std::unique_ptr<T, DeleterType> get()
    {
        if (pool_.empty())
        {
            throw std::logic_error("no more object");
        }

        //every time add custom deleter for default unique_ptr
        std::unique_ptr<T, DeleterType> ptr(pool_.back().release(), [this](T* t)
        {
            pool_.push_back(std::unique_ptr<T>(t));
        });

        pool_.pop_back();
        return std::move(ptr);
    }

@xiaonaiquan
Copy link

确实有这个问题,楼上说的对

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants