多线程实践之对象池

多线程实践

整理自陈硕大大的 多线程网络编程 ,大佬真的牛

对象池

说明:factory里面保存者对象,对象用ID标识,当相同I/D请求则把当前对象池对象返回,如果对象不被任何地方使用对象要被析构

版本1:

template<typename T> 
class FastFactory {
 public:
    shared_ptr<T> get(string id) {
        unique_lock<mutex> lock(m_mutex_);
        shared_ptr<T> ptr = m_list_[id];
        if (!ptr) {
            ptr = make_shared<T>(id);
        }
        return ptr;
    }
 private:
    mutex m_mutex_;
    unordered_map<string, shared_ptr<T> > m_list_;
};

问题所在:
unordered_map保存的shared_ptr永远不会析构一直强引用绑着,我们需要如果对象不被任何地方使用对象要被析构

​ 用锁因为这里已经出现了共享变量的读取以及竟态条件的判断

版本2 加入 weak_ptr

template<typename T>
class FastFactory {
 public:
    shared_ptr<T> get(string id) {
        unique_lock<mutex> lock(m_mutex_);
        weak_ptr<T>& ptr = m_list_[id]; //
        shared_ptr<T> ret = ptr.lock();
        if (!ret) {
            ret = make_shared<T>(id);
            ptr = ret;
        }
        return ret;
    }
 private:
    mutex m_mutex_;
    unordered_map<string, weak_ptr<T> > m_list_;
};

说明:解决了版本1不释放的问题

问题所在:

​ 但是unordered_map这个list的size没有减少,因为只要有新ID size就会增加,这就不对了

版本3 加入定制的析构函数

class Test {
public:
    Test(string id) :
        m_id(id) {

    }

    const string& key() const { return m_id; }
private:
    string m_id;
};

template<typename T>
class FastFactory {
 public:
    shared_ptr<T> get(string id) {
        unique_lock<mutex> lock(m_mutex_);
        weak_ptr<T>& ptr = m_list_[id]; //
        shared_ptr<T> ret = ptr.lock();
        if (!ret) {
            ret.reset(new T(id), bind(&FastFactory::deleteObject, this, std::placeholders::_1));
            ptr = ret;
        }
        return ret;
    }
 private:
    void deleteObject(T* ptr) {
        if (ptr) {
            unique_lock<mutex> lock(m_mutex_);
            m_list_.erase(ptr->key());
        }
        delete ptr;
    }
    typedef function<void(T*)> functor;
    mutex m_mutex_;
    unordered_map<string, weak_ptr<T> > m_list_;
};

说明:使用deleteObject来进行 对象池的移除

问题:bind使用this进行绑定,存在可能性对象池销毁了,造成异常

版本4 加入enable_shared_from_this

class Test {
public:
    Test(string id) :
        m_id(id) {

    }

    const string& key() const { return m_id; }
private:
    string m_id;
};

template<typename T>
class FastFactory : public enable_shared_from_this<FastFactory<T> >{
 public:
    shared_ptr<T> get(string id) {
        unique_lock<mutex> lock(m_mutex_);
        weak_ptr<T>& ptr = m_list_[id]; //
        shared_ptr<T> ret = ptr.lock();
        if (!ret) {
            ret.reset(new T(id), bind(&FastFactory::deleteObject, this->shared_from_this(), std::placeholders::_1));
            ptr = ret;
        }
        return ret;
    }
 private:
    void deleteObject(T* ptr) {
        if (ptr) {
            unique_lock<mutex> lock(m_mutex_);
            m_list_.erase(ptr->key());
        }
        delete ptr;
    }
    typedef function<void(T*)> functor;
    mutex m_mutex_;
    unordered_map<string, weak_ptr<T> > m_list_;
};

说明:加入enable_shared_from_this让类shared_ptr给外部

问题:这延长了FastFactory的生命周期

版本5 弱回调

如果对象活着就调用,使用weak_ptr

class Test {
public:
    Test(string id) :
        m_id(id) {
        std::cout << "Test() id = " << m_id << std::endl;
    }
    ~Test()
    {
        std::cout << "~Test() id = " << m_id << std::endl;
    }
    const string& key() const { return m_id; }
private:
    string m_id;
};

template<typename T>
class FastFactory : public enable_shared_from_this<FastFactory<T> >{
 public:
    shared_ptr<T> get(string id) {
        unique_lock<mutex> lock(m_mutex_);
        weak_ptr<T>& ptr = m_list_[id]; //
        shared_ptr<T> ret = ptr.lock();
        if (!ret) {
            ret.reset(new T(id), bind(&FastFactory::deleteObject, this->shared_from_this(), std::placeholders::_1));
            ptr = ret;
        }
        return ret;
    }
 private:
    static void deleteObject(const weak_ptr<FastFactory<T> >& weak_factory, T* ptr) {
        shared_ptr<FastFactory<T> > factory = weak_factory.lock();
        if (ptr) {
            factory->removePtr(ptr);
        }
    }

    void removePtr(T* ptr) {
        if (ptr) {
            unique_lock<mutex> lock(m_mutex_);
            auto key = m_list_.find(ptr->key());
            if ( (key != m_list_.end()) && (key->second.expired()) ) {
                m_list_.erase(ptr->key());
            }
        }
        delete ptr;
    }
    typedef function<void(T*)> functor;
    mutex m_mutex_;
    unordered_map<string, weak_ptr<T> > m_list_;
};

说明:使用静态deleteObject,作为bind的显示参数,之后内部调用removePtr来进行析构

这样 对象池和被创建的对象就互相不是强绑定的依赖了

posted @ 2021-06-27 22:35  make_wheels  阅读(282)  评论(0编辑  收藏  举报