• 工厂模式和对象池


    工厂模式和对象池

    c++下构造一个对象一般的做法是采用new&delete

    复制代码
    class exp{
    //anything }; exp
    *p = new exp; //do anything delete p;
    复制代码

    考虑到new&delete本身的实现,背后的内存管理采用的是统一的malloc&free,如果要对不同的类型采用不同的内存管理策略,就需要对不同的类类型重载new&delete操作符

    复制代码
    class exp1{
    public:
        //any thing
    public:
        void * operator new(size_t size){
            return malloc(size);
        }
    
        void operator delete(void *p){
            free(p);
        }
    
        void * operator new[ ](size_t size){
            return malloc(size);
        }
    
        void operator delete[ ](void *p){
            free(p);
        }        
    };    
    
    class exp2{
    public:
        //any thing
        std::allocator<exp2> alloc;
    public:
        void * operator new(size_t size){
            return alloc.allocate(1);
        }
    
        void operator delete(void *p){
            alloc.deallocate((exp2*)ptr, 1);
        }
    
        void * operator new[ ](size_t size){
            return alloc.allocate(size/sizeof(exp2));
        }
    
        void operator delete[ ](void *p, size_t size){
            alloc.deallocate((exp2*)ptr, size/sizeof(exp2));
        }        
    };    
    复制代码

    或是另一个做法,对不同的类型构造采用硬编码

    复制代码
    //exp1
    class exp1{
    //any thing
    };
    
    std::allocator<exp1> alloc;
    exp1 * p = alloc(1);
    new(p) exp1();
    //do anything
    p->~expq();
    alloc.deallocate((exp1*)ptr, 1);
    
    //exp2
    class exp2{
    //any thing
    };
    
    exp2 * p = nedmalloc(siezof(exp2));
    new(p) exp2();
    //do anything
    p->~exp2();
    nedfree(p);
    复制代码

    不过这2种做法都需要多写大量繁琐的代码。依赖于C++的模板机制,我们可以写出如下的简化代码,

    复制代码
    template <typename T, typename _Allocator_ = boost::pool_allocator<T> >
    class abstract_factory{
    public:
        abstract_factory(){
        }
    
        ~abstract_factory(){
        }
    
        T * create_product(){
            T * pT =  (T*)_Allocator.allocate(1);
            new(pT) T();
            
            return pT;
        }
            
            void release_product(T * pT){
            pT->~T();
                    _Allocator.deallocate(pT, 1);
            }          
    }
    复制代码

    考虑到支持带参数的构造函数,我写了一坨丑陋的代码

    复制代码
    template <typename t1> 
    T * create_product(t1 _t1);
    
    template <typename t1, typename t2>
    T * create_product(t1 _t1, t2 _t2);
    
    //...
    
    template <typename t1, typename t2, typename t3, typename t4, typename t5, typename t6, typename t7, typename t8, typename t9, typename t10>
    T * create_product(t1 _t1, t2 _t2, t3 _t3, t4 _t4, t5 _t5, t6 _t6, t7 _t7, t8 _t8, t9 _t9, t10 _t10);
    复制代码

    这样对象的创建我们就可以采用如下写法

    复制代码
    class exp1{
    public:
         exp1(int n) : a(n){}
         ~exp1(){}
    
    private:
         int a;
    }
    
    abstract_factory<exp1> _afexp1;
    shared_ptr pexp1(_afexp1.create_product(1), bind(&abstract_factory<exp1>::release_product, &_afexp1, _1));
    //do anything
    复制代码

    这陀东西比较糟糕的一个地方是,只支持一次创建一个对象,原因是背后的对象池的管理机制,我采用了一种有趣的做法,就是对回收的对象析构之后,在回收的内存上保存上次回收的内存地址,以此来实现了一个链式的结构。

    但是数组本身也可以采用vector之类的现有容器

    class exp1{
    //any thing
    };
    
    std::vector<exp1> vexp1;

     为了提高在多线程下的访问效率,我采用了一种类似thread-cache的做法,就是将一个对象链表视为一个mirco_pool,创建多个mirco_pool。通过为每个mirco_pool加锁,访问mirco_pool时先尝试try_lock,失败则对下一个mirco_pool尝试try_lock,成功后再执行分配&构造或是析构回收操作,来降低锁竞争的开销。

    复制代码
    for(uint32_t i = 0; i < count; i++){
        boost::mutex::scoped_lock lock(_mirco_pool[i]._mu, boost::try_to_lock);
    
        if (lock.owns_lock()){
            if (_mirco_pool[i]._pool != 0){
                pT = (T*)_mirco_pool[i]._pool;
                _mirco_pool[i]._pool = *((char**)_mirco_pool[i]._pool);
    
                break;
            }
        }
    }
    复制代码

    代码地址:https://github.com/qianqians/Hemsleya/blob/master/base/concurrent/abstract_factory/abstract_factory.h

    参考阅读:

    抽象工厂模式 http://zh.wikipedia.org/zh-cn/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82

    对象池 http://baike.baidu.com/view/262255.htm

  • 相关阅读:
    CSS
    Html5
    [LeetCode] 78. Subsets(子集)
    [LeetCode] 22. Generate Parentheses(括号生成器)
    [LeetCode] 406. Queue Reconstruction by Height(按身高重排队列)
    [LeetCode] 46. Permutations(全排列)
    [LeetCode] 94. Binary Tree Inorder Traversal(二叉树的中序遍历)
    [LeetCode] 338. Counting Bits(数比特位)
    [LeetCode] 763. Partition Labels(标签划分)
    [LeetCode] 20. Valid Parentheses(有效的括号)
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3295712.html
Copyright © 2020-2023  润新知