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; } }
}
参考阅读:
抽象工厂模式 http://zh.wikipedia.org/zh-cn/%E6%8A%BD%E8%B1%A1%E5%B7%A5%E5%8E%82