看jrtplib源码时,对其中的内存管理不理解,遂向高手请教,把所得记于此:
主要的两个类:
class RTPMemoryManager
{
public:
RTPMemoryManager() { }
virtual ~RTPMemoryManager() { }
virtual void *AllocateBuffer(size_t numbytes, int memtype) = 0;
virtual void FreeBuffer(void *buffer) = 0;
};
class RTPMemoryObject
{
protected:
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryObject(RTPMemoryManager *memmgr) : mgr(memmgr) { }
#else
RTPMemoryObject(RTPMemoryManager *memmgr) { }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
virtual ~RTPMemoryObject() { }
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
RTPMemoryManager *GetMemoryManager() const { return mgr; }
void SetMemoryManager(RTPMemoryManager *m) { mgr = m; }
#else
RTPMemoryManager *GetMemoryManager() const { return 0; }
void SetMemoryManager(RTPMemoryManager *m) { }
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
#ifdef RTP_SUPPORT_MEMORYMANAGEMENT
private:
RTPMemoryManager *mgr;
#endif // RTP_SUPPORT_MEMORYMANAGEMENT
};
据说下面这个类RTPMemoryObkect的作用是为了把具体工作的类与RTPMemoryManager分离(设计模式->适配器模式)
首先,它有自己的new:
inline void *operator new[](size_t numbytes, RTPMemoryManager *mgr, int memtype)
{
if (mgr == 0)
return operator new[](numbytes);
return mgr->AllocateBuffer(numbytes,memtype);
}
重载 operator new 的参数个数是可以任意的 , 只需要保证第一个参数为 size_t, 返回类型为 void * 即可 , 而且其重载的参数类型也不必包含自定义类型 。
然后这样使用:
#define RTPNew(a,b) new(a,b)
uint8_t *localhostname = RTPNew(GetMemoryManager(),RTPMEM_TYPE_OTHER) uint8_t [localhostnamelength+1];
class MyMemoryManager : public RTPMemoryManager
{
public:
MyMemoryManager()
{
mutex.Init();
alloccount = 0;
freecount = 0;
}
~MyMemoryManager()
{
std::cout << "alloc: " << alloccount << " free: " << freecount << std::endl;
}
void *AllocateBuffer(size_t numbytes, int memtype)
{
mutex.Lock();
void *buf = malloc(numbytes);
std::cout << "Allocated " << numbytes << " bytes at location " << buf << " (memtype = " << memtype << ")" << std::endl;
alloccount++;
mutex.Unlock();
return buf;
}
void FreeBuffer(void *p)
{
mutex.Lock();
std::cout << "Freeing block " << p << std::endl;
freecount++;
free(p);
mutex.Unlock();
}
private:
int alloccount,freecount;
JMutex mutex;
};
最后这样使用:
MyMemoryManager mgr;
RTPSession sess(0, &mgr);
这种方法很巧妙,也很难看懂,example里面的内存分配方式简易了点,自己实现时可以考虑内存池,因为RTP数据发送时申请和释放内存还是挺频繁的。