资源池 ResourcePool

ResourcePool<T>::singleton()->get_resource(id, arg1);

template <typename T>
class ResourcePool { ... }

是个类模板,单例模式。

主要成员: get_resource / return_resource

有个 LocalPool 成员, 依赖它实现 get 和 return。

LocalPool

有一个概念是 FreeChunk, 用于挂载空闲的资源。

数据结构为 : { nfree,ids[] }

资源池整体的逻辑就是, 先从freeChunk上取,如果freeChunk上没有,那么从大的内存块上切,如果无空间可切了,那就只能返回NULL了。

为什么要先从freeChunk上取呢?因为这里挂载的是旧的 归还的内存地址。 为了尽可能的实现资源的复用,而不是每次都从block上切。毕竟block也是可以有多个的,当前block切完了,可能需要创建新的block。

主要代码:

brpc - ResourcePool_brpc

上面的是取资源的主要逻辑。

而归还资源,肯定是往freeChunk上挂载。


使用柔性数组构建FreeChunk对象---节省空间

brpc - ResourcePool_brpc_02


unsafe_address_resource

FreeChunk保存的是 resource_id , 而这个resource_id 是什么呢? 它是从block上切下来的对象的编号, 也就是第几个切的那么这个id就是几。

if (_cur_block && _cur_block->nitem < BLOCK_NITEM) {            \
        id->value = _cur_block_index * BLOCK_NITEM + _cur_block->nitem; \  // id->value是 item的编号

归还资源时,挂载到freeChunk上的就是这个 resource_id, 而从freeChunk上取资源,就是取resource_id ,然后根据resource_id 计算出具体的地址。


其它

在我的工作中,也实现过功能类似的模块(整体思路基本一致,实现的时候没有任何资源池代码的了解,场景来了,优化思路和实现想法自然就来了),但只是一个单线程的内存池的优化(场景就是单线程),brpc资源池这里对模板的使用还是值得学习一下的(平时自己写模板代码的机会比较少)。

有时候,看别人的代码是一个探索的过程,我觉得比看小说有意思多了,看小说就像看我的这篇唠叨话,这些东西都是喂给你的。而看别人代码,是有一个“猜”与“验证”的环节存在的。