简单易用的对象池

源码地址: https://github.com/ylmbtm/GameProject3

经常有群友问到本项目的对象池,今天有点时间就给大家简单介绍一下,这个对象池的实现只有一个头文件MemObjectPool.h,这个文件在项目源码的\Src\ServerEngine目录下,里面包含全部的声明和实现,非常独立,你甚至可以单独把这个文件拷到你自己的项目中,它的使用非常简单,只需要在你希望支持对象池的类对象的声明文件里加一行宏代码,这个类的申请和释放就自动支持池管理了,下面就是代码示例:

class TestA
{
public:
  MEM_OBJECT_POOL_SUPORT(TestA);
}

这个宏里做了什么事呢,我们继续看代码:


#define MEM_OBJECT_POOL_SUPORT(ClassName) \
  typedef MemObjectPool<##ClassName##> PoolType; \
  static void* operator new(size_t size) \
  { \
    if(size != sizeof(ClassName))\
    {\
      return NULL;\
    }\
    return GetObjectPool()->CreateMemObject(); \
  } \
  static void operator delete(void* pointee) \
  { \
    GetObjectPool()->FreeMemObject((ClassName*)pointee); \
  } \
  static PoolType* GetObjectPool() \
  { \
    static PoolType s_MemObjectPool; \
    return &s_MemObjectPool; \
  }

原理其实非常简单,就是通过重载placement new 和 delete操作来改变这个类在创建和销毁实例时的内存使用方式, 有些人可能不太明白,下面再详细说一下:

假设我们有一个类 class TestA,

那么在申请创建一个新实例TestA * a=new TestA时,

实际上执行如下3个过程:

(1)调用operator new分配内存,operator new (sizeof(TestA)) ;

(2)调用构造函数生成类对象,TestA::TestA();

(3)返回相应指针;

在这三步中,分配内存就是由第一步operator new(size_t)来完成的,而我这个对象池就是通过重载operator new来实现的,通过重载new操作,我们将原来的从系统分配内存,直接改成从我们的对象池来分配内存。而重载delete操作也是同样,将原来的系统释放内存改为由我们的对象池来管理内存的释放。

当前上面我在示中例用到的宏是非线程安全的,如果类对象有跨线程申请和释放则需要用到另一个宏:

MEM_OBJECT_POOL_SUPORT_MT(TestA)

这个宏和之前宏功能一样,只是在内存的申请释放时增加了锁机制,是线程安全的,但我们用C++做游戏时,逻辑功能一般都是在一个单线程中,所以在我们在逻辑功能里使用的对象实例就可以不必要线程安全,这样我们用非加锁的对象池来追求极致的性能。

这个内存池的通过批量申请以及预申请方式提高性能,还尽可能减少内存碎片。

大家还有什么不理解的地方,可以私信,有时间我会给大家继续讲解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值