简介
ResourcePool用于管理资源,负责资源的分配以及回收
结构
BlockGroup:资源池中包含多个BlockGroup,最多65536个
Block:一个BlockGroup中包含多个Block,最多(1<<16)个;1个Block中包含BLOCK_NITEM个类型为T的资源,BLOCK_NITEM由类模板ResourcePoolBlockItemNum中的静态成员value决定
template <typename T>
class ResourcePoolBlockItemNum {
static const size_t N1 = ResourcePoolBlockMaxSize<T>::value / sizeof(T);
static const size_t N2 = (N1 < 1 ? 1 : N1);
public:
static const size_t value = (N2 > ResourcePoolBlockMaxItem<T>::value ?
ResourcePoolBlockMaxItem<T>::value : N2);
};
template <typename T> struct ResourcePoolBlockMaxSize {
static const size_t value = 64 * 1024; // bytes
};
template <typename T> struct ResourcePoolBlockMaxItem {
static const size_t value = 256;
};
分配
资源分配是通过以下几个接口
template <typename T> inline T* get_resource(ResourceId<T>* id) {
return ResourcePool<T>::singleton()->get_resource(id);
}
// Get an object whose constructor is T(arg1)
template <typename T, typename A1>
inline T* get_resource(ResourceId<T>* id, const A1& arg1) {
return ResourcePool<T>::singleton()->get_resource(id, arg1);
}
// Get an object whose constructor is T(arg1, arg2)
template <typename T, typename A1, typename A2>
inline T* get_resource(ResourceId<T>* id, const A1& arg1, const A2& arg2) {
return ResourcePool<T>::singleton()->get_resource(id, arg1, arg2);
}
空闲资源的定义是通过ResourcePoolFreeChunk
template <typename T, size_t NITEM>
struct ResourcePoolFreeChunk {
size_t nfree;
ResourceId<T> ids[NITEM];
};
// for gcc 3.4.5
template <typename T>
struct ResourcePoolFreeChunk<T, 0> {
size_t nfree;
ResourceId<T> ids[0];
};
分配规则
- 优先从LocalPool空闲资源表中分配
- 如果无法从LocalPool空闲资源表中分配,则从ResourcePool的空闲资源表中分配
- 从LocalPool中的Block分配
- 从ResourcePool中BlockGroup的Block分配
释放
释放是通过下面接口回收到资源池中
template <typename T> inline int return_resource(ResourceId<T> id) {
return ResourcePool<T>::singleton()->return_resource(id);
}
回收规则为
- 首先放到本地池中的空闲数组中
- 如果本地池中的空闲数组已满,则将本地池中的空闲数组复制到全局资源池中的空闲资源数组中,将当前的资源放到本地池中的空闲数组
inline int return_resource(ResourceId<T> id) {
// Return to local free list
if (_cur_free.nfree < ResourcePool::free_chunk_nitem()) {
_cur_free.ids[_cur_free.nfree++] = id;
BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_ADD1;
return 0;
}
// Local free list is full, return it to global.
// For copying issue, check comment in upper get()
if (_pool->push_free_chunk(_cur_free)) {
_cur_free.nfree = 1;
_cur_free.ids[0] = id;
BAIDU_RESOURCE_POOL_FREE_ITEM_NUM_ADD1;
return 0;
}
return -1;
}