分析jrtplib库的内存管理类

5806阅读 0评论2011-11-05 yulc
分类:C/C++

jrtplib允许用户自己管理内存. 默认情况下, 该库会调用运算符new/delete来分配/释放运行过程中需要的内存空间.

这两天研究jrtlib-3.8.2库,原本是研究其rtp/rtcp的实现, 在跟踪代码时,却发现它提供给用户管理内存的接口,设计得非常巧妙, 如教科书般的将C++各种特性展现出来.

这中间主要是两个类:

RTPMemoryManager 这个类是个纯虚类:

  1. class RTPMemoryManager
  2. {
  3. public:
  4.         RTPMemoryManager() { }
  5.         virtual ~RTPMemoryManager() { }

  6.         virtual void *AllocateBuffer(size_t numbytes, int memtype) = 0;
  7.         virtual void FreeBuffer(void *buffer) = 0;
  8. };

最主要的是这个类有自己的new/delete以及new[]/delete[]运算符, 注意这并非重载全局的new/delete.这里仅贴出来重载new/delete的部分:

  1. inline void *operator new(size_t numbytes, RTPMemoryManager *mgr, int memtype)
  2. {
  3.         if (mgr == 0)
  4.                 return operator new(numbytes);
  5.         return mgr->AllocateBuffer(numbytes,memtype);
  6. }

  7. inline void operator delete(void *buffer, RTPMemoryManager *mgr, int memtype)
  8. {
  9.         if (mgr == 0)
  10.                 operator delete(buffer);
  11.         else
  12.                 mgr->FreeBuffer(buffer);
  13. }

用户如果需要自己来管理内存,只要编写自己的class,并继承自RTPMemoryManager 即可,当然最重要的是需要重载该类的纯虚函数. 如果仅仅是这些, 还谈不上设计得巧妙, 还有个重要的类是

RTPMemoryObject 这个类非常简单:

  1. class RTPMemoryObject
  2. {
  3. protected:
  4.         RTPMemoryObject(RTPMemoryManager *memmgr) : mgr(memmgr) { }
  5.         virtual ~RTPMemoryObject() { }

  6.         RTPMemoryManager *GetMemoryManager() const { return mgr; }
  7.         void SetMemoryManager(RTPMemoryManager *m) { mgr = m; }

  8. private:
  9.         RTPMemoryManager *mgr;
  10. };
 
根据jrtplib库的实现,这个类的作用,是将具体工作的class与RTPMemoryManager class分离, 例如将RTPSession class 与 RTPMemoryManager class 分离. 这在设计模式里貌似是叫适配器模式.
整个jrtplib库中最重要的class, 也就是RTPSession, 它是继承自:RTPMemoryObject
这样在内部实现中,通过RTPMemoryObject::GetMemoryManager() 函数来将用户实现的内存管理类获得,然后通过new的重载运算符 从而调用RTPMemoryManager::AllocateBuffer , 语法如下:
OneClass *p = new(GetMemoryManager() /* 返回RTPMemoryManager指针 */, x) OneClass();
根据C++ operator new的描述, 这个调用,相当于是调用函数:
void *operator new(size_t numbytes, RTPMemoryManager *mgr, int memtype);
其中,第一个参数是OneClass的字节数,
第二个参数是上面new()中的第一个参数,
第三个参数是上面new()中的第二个参数.
 
而由于C++多态的特性, 在RTPMemoryManager类重载的那个new实现中, AllocateBuffer function, 最终会调用用户编写的那个重载过的函数. 这在jrtplib库中的examples/examples5.cpp 文件中有示例.
 
代码看到这, 其实已经理解得差不多了, 确实很久没有看到设计得这么简洁的类了.但这是在现有的代码上分析,看到的是已经设计好的class和接口,自然一目了然. 那如果没有RTPMemoryObject这个类, 代码会是什么样子呢?
我觉得要么是增加全局的RTPMemoryManager实例, 这要求程序员做更多的事情,明显不是一个好的方案.
第二种方式是, 在RTPSession中增加RTPMemoryManager指针, 在构造RTPSession类时,将该指针传入,这同目前的实现接口是一样的,这种方式我没有想到有什么不好的地方,这是"has a", 而目前的实现更像是"is a".
 
 
 
上一篇:《画皮》新版真的不错
下一篇:rtcp中sender report中的时间戳