Boost Development Guide-3.8pool

pool

The memory pool pre-allocates a large memory space, and then a certain algorithm can be used in it to realize efficient and fast custom memory allocation.

The boost.pool library implements a fast and compact memory pool library based on the idea of ​​simple separated storage. It can not only manage a large number of objects, but also be used as a memory allocator for STL. To some extent, it is similar to a small garbage collection mechanism, which is very efficient when a large number of small objects need to be allocated/released, and there is no need to consider delete at all.

The pool library consists of four components: the simplest pool, object_pool for allocating class instances, singleton_pool for singleton memory pools, and pool_alloc for standard libraries.

Pool is the simplest and easiest-to-use memory pool class, which can return a memory pointer of a simple data type (POD). It is located in the namespace boost. In order to use the pool component, the header file <boost/pool/pool.hpp> needs to be included, namely:

#include <boost/pool/pool.hpp>
using namespace boost;

The pool component itself has no external dependencies, but the singleton_pool in the header file pool_fwd.hpp indirectly depends on the boost.system library. In order to avoid unnecessary link errors, you can define the macro BOOST_SYSTEM_NO_DEPRECATED before the include statement.

class summary

template <typename UserAllocator = default_user_allocator_new_delete>
class pool
{
    
    
public:
   explicit pool (size_type requested_size); //构造函数
   ~pool(); //析构函数
   size_type get_requested_size() const; //分配块大小
   void * malloc(); //分配内存
   void * ordered_malloc();
   void ordered_malloc(size_type n);
   bool is_from(void * chunk) const;
   void free (void * chunk); //归还内存
   void ordered_free(void * chunk);
   void free(void * chunks, size_type n);
   void ordered_free(void* chunks, size_type n);
   bool release_memory(); //释放内存
   bool purge_memory();
};

operation function

The template type parameter UserAllocator of the pool is a user-defined memory allocator, which implements a specific memory allocation algorithm, and usually can directly use the default default_user_allocator_new_delete, which internally uses new[ ] and delete[ ] to allocate memory.

The constructor of pool accepts an integer requested_size of type size_type, which indicates the size of the memory block allocated by the pool each time (not the size of the pool memory pool). This value can be obtained with get_requested_size(). The pool will automatically apply for or return the used memory to the system as needed, and when it is destroyed, the pool will automatically release all the memory blocks it holds.

The behavior of member functions malloc() and ordered_malloc() is very similar to the global function malloc() in c, using void* pointer to return the memory block allocated from the memory pool, the size is the requested_size specified in the constructor. If memory allocation fails, the function returns 0 and no exception is thrown. malloc() arbitrarily allocates a memory block from the memory pool, while ordered_malloc() merges the free block list while allocating. The form of ordered_malloc() with parameters can also continuously allocate n blocks of memory. The allocated memory block can use the is_from() function to test whether it is allocated from this memory pool.

The set of functions corresponding to malloc() is free(), which is used to manually release previously allocated memory blocks. These memory blocks must be allocated from this memory pool (is_from(chunk) == true). In general, the memory pool will automatically manage memory allocation, and the free() function should not be called, unless you think that the space in the memory pool is insufficient and the allocated memory must be released.

Finally, there are two member functions: release_memory() allows the memory pool to release all unallocated memory, but allocated memory blocks are not affected; purge_memory() forces the release of all memory held by the pool, regardless of whether the memory block is use. In fact, the pool's destructor is called purge_memory(). These two functions should not be called manually by programmers under normal circumstances.

usage

The pool is easy to use, you can allocate memory like malloc() in c, and then use it as you like. Unless there are special requirements, it is not necessary to call free() to release the allocated memory, and the pool will manage the memory well. For example:

#define BOOST_SYSTEM_NO_DEPRECATED //避免链接boost.system库
int main()
{
    
    
	pool<> pl(sizeof(int)); //一个可分配int的内存池

	int* p = static_cast<int*>(pl.malloc()); //必须把void*转换成需要的类型
	assert(pl.is_from(p)); //测试是否分配出去

	pl.free(p); //释放内存池分配的内存块
	for (int i = 0; i < 100; ++i) //连续分配大量的内存
	{
    
    
		pl.ordered_malloc(10);
	}
} //内存池对象析构,所有分配的内存在这里都被释放

Because the pool does not throw an exception when allocating memory fails, the actual code should check the pointer returned by the malloc() function to prevent null pointer errors, but usually this situation rarely occurs:

int *p = static_cast<int*>(p1.malloc());
if(p != nullptr)
  ...

There is no more explanation about pool<>, because it is really easy to use, just one thing to note: it can only be used as a memory pool for common data types such as int, double, etc., and cannot be applied to complex classes and objects, because it Only allocate memory, do not call the constructor, this time we need to use object_pool.

code example

#define BOOST_SYSTEM_NO_DEPRECATED

#include <boost/pool/pool.hpp>
using namespace boost;

int main()
{
    
    
	pool<> pl(sizeof(int));

	int* p = static_cast<int*>(pl.malloc());
	assert(pl.is_from(p));

	pl.free(p);
	for (int i = 0; i < 100; ++i)
	{
    
    
		pl.ordered_malloc(10);
	}
	return 0;
}

Guess you like

Origin blog.csdn.net/qq_36314864/article/details/132061785