singleton_pool与pool的接口完全一致,可以分配简单数据类型(POD)的内存指针,但它是一个单件,并提供线程安全。
由于目前Boost还未提供标准的单件库,singleton_pool在其内部实现了一个较简单、泛型的单件类,保证在main()函数运行之前就创建单件(详情可参考4.6.1小节,117页)。
singleton_pool位于名字空间boost,为了使用singleton_pool组件,需要包含头文件<boost/pool/singleton_pool.hpp>,即:
#include <boost/pool/singleton_pool.hpp>
using namespace boost;
3.11.1 类摘要
singleton_pool的类摘要如下:
template <typename Tag, unsigned RequestedSize>
class singleton_pool
{
public:
static bool is_from(void * ptr);
static void * malloc();
static void * ordered_malloc();
static void * ordered_malloc(size_type n);
static void free(void * ptr);
static void ordered_free(void * ptr);
static void free(void * ptr, std::size_t n);
static void ordered_free(void * ptr, size_type n);
static bool release_memory();
static bool purge_memory();
};
3.11.2 用法
singleton_pool主要有两个模板类型参数(其余的可以使用缺省值)。第一个Tag仅仅是用于标记不同的单件,可以是空类,甚至是声明(这个用法还被用于boost.exception,参见4.9小节,136页)。第二个参数RequestedSize等同于pool构造函数中的整数requested_ size,指示pool分配内存块的大小。
singleton_pool的接口与pool完全一致,但成员函数均是静态的,因此不需要声明singleton_pool的实例[1],直接用域操作符::来调用静态成员函数。因为singleton_pool是单件,所以它的生命周期与整个程序同样长,除非手动调用release_memory()或purge_memory(),否则singleton_pool不会自动释放所占用的内存。除了这两点,singleton_pool的用法与pool完全相同。
下面的代码示范了singleton_pool的用法:
#include <boost/pool/singleton_pool.hpp>
using namespace boost;
struct pool_tag{}; //仅仅用于标记的空类
typedef singleton_pool<pool_tag, sizeof(int)> spl; //内存池定义
int main()
{
int *p = (int *)spl::malloc(); //分配一个整数内存块
assert(spl::is_from(p));
spl::release_memory(); //释放所有未被分配的内存
} //spl的内存直到程序结束才完 //全释放,而不是退出作用域
singleton_pool在使用时最好使用typedef来简化名称,否则会使得类型名过于冗长而难以使用。如代码中所示:
typedef singleton_pool<pool_tag, sizeof(int)> spl;
用于标记的类pool_tag可以再进行简化,直接在模板参数列表中声明tag类,这样可以在一条语句中完成对singleton_pool的类型定义,例如:
typedef singleton_pool<struct pool_tag, sizeof(int)> spl;
[1] 因为使用了单件模式,用户也无法创建singleton_pool的实例。