c++ boost库之pool内存池

1. 内存池技术优点

 提前分配,可减少内存的分配和释放的开销,提高效率; 减少内存碎片化;

 2. pool

只能用于普通数据类型如 int,double等的内存池;

// boost库源码:

template 
class pool 
{
public:
  ...

  // construct/copy/destruct
  //指示每次pool分配内存块的大小(不是内存池大小);
  explicit pool(const size_type s, const size_type = 32, const size_type m = 0) : chunk_size(s), max_alloc_size(m) {}
  ~pool()
  {
     purge_memory();
  }

  bool release_memory()
  {
     bool ret = free_list.empty() ? false : true;
     for(std::set::iterator pos = free_list.begin(); pos != free_list.end(); ++pos)
     {
        (user_allocator::free)(static_cast(*pos));
     }
     free_list.clear();
     return ret;
  }

  //强制释放pool池内存;
  bool purge_memory()
  {
     bool ret = free_list.empty() && used_list.empty() ? false : true;
     for(std::set::iterator pos = free_list.begin(); pos != free_list.end(); ++pos)
     {
        (user_allocator::free)(static_cast(*pos));
     }
     free_list.clear();
     for(std::set::iterator pos = used_list.begin(); pos != used_list.end(); ++pos)
     {
        (user_allocator::free)(static_cast(*pos));
     }
     used_list.clear();
     return ret;
  }
  

  //失败返回0;
  void * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
  {
     void* ret;
     if(free_list.empty())
     {
     	//空闲链表为空,说明没有分配过;执行内存申请;
        ret = (user_allocator::malloc)(chunk_size);
        VALGRIND_MAKE_MEM_UNDEFINED(ret, chunk_size);
     }
     else
     {
     	//空闲链表非空,直接从空闲链表取块;
        ret = *free_list.begin();
        free_list.erase(free_list.begin());
        VALGRIND_MAKE_MEM_UNDEFINED(ret, chunk_size);
     }

	 //分配后,这块内存被用了;加入到已使用的内存块链表;
     used_list.insert(ret);

     return ret;
  }

  void * ordered_malloc()
  {
     return (this->malloc)();
  }

  //连续分配n块内存;
  void * ordered_malloc(size_type n)
  {
     if(max_alloc_size && (n > max_alloc_size))
        return 0;
     void* ret = (user_allocator::malloc)(chunk_size * n);
     used_list.insert(ret);
     return ret;
  }

  //仅仅从已使用链表移除; 并没有真正真正的释放内存;
  void free BOOST_PREVENT_MACRO_SUBSTITUTION(void *const chunk)
  {
     BOOST_ASSERT(used_list.count(chunk) == 1);
     BOOST_ASSERT(free_list.count(chunk) == 0);
     used_list.erase(chunk);
     free_list.insert(chunk);
     VALGRIND_MAKE_MEM_NOACCESS(chunk, chunk_size);
  }

  void ordered_free(void *const chunk)
  {
     return (this->free)(chunk);
  }

  void free BOOST_PREVENT_MACRO_SUBSTITUTION(void *const chunk, const size_type)
  {
     BOOST_ASSERT(used_list.count(chunk) == 1);
     BOOST_ASSERT(free_list.count(chunk) == 0);
     used_list.erase(chunk);
     (user_allocator::free)(static_cast(chunk));
  }

  void ordered_free(void *const chunk, const size_type n)
  {
     (this->free)(chunk, n);
  }

  //测试trunk块是否是从这个内存池分配的;
  bool is_from(void *const chunk) const
  {
     return used_list.count(chunk) || free_list.count(chunk);
  }

protected:
	//chunk_size:内存块大小 
   size_type chunk_size, max_alloc_size;
   //空闲链表,已使用的链表
   std::set free_list, used_list;
};

#endif

} // namespace boost

使用示例:

{
	//内存池中 每个内存块的大小为sizeof(int),使用默认的分配器;
	pool<> pl(sizeof(int));

	//假如项目最大只想用10个内存块
	#define MAX_POOL_BLK 10
	int *p[MAX_POOL_BLK] = {0};
	for(int i = 0; i < MAX_POOL_BLK; ++i){
		p[i] = static_cast(pl.malloc());//这十个内存块都是实际调用系统函数分配出来的;
	}
	//到这里,pool内存池中拥有10个 每个大小为 sizeof(int) 的内存块了; 并且都被占用了;

	for(int i = 0; i < MAX_POOL_BLK; ++i){
		pl.free(p[i]); //并没有真正释放内存,仅仅是将内存块变成空闲的了;
	}
	//到这里,pool内存池中依然拥有10个 每个大小为 sizeof(int) 的内存块; 但是内存块都是空闲的;
	
	//下次需要用到一个内存块,可以直接调用 pl.malloc(); 
	//在需要的内存块数量不超过上述10个时,使用的是之前分配好的空闲的; 当大于10个时(可扩容),才会调用系统函数真正申请内存空间;
	cout << "is_from: " << pl.is_from(p[0]) << endl;


	//接下来,需要时 p[i] = static_cast(pl.malloc())
	//不需要时 pl.free(p[i]);

	//离开作用域时自动调用 pl.purge_memory();释放内存;
}

 

3. object_pool

用于类实例(对象)的内存池

 继承自pool, 其中多了 construct()和destroy()函数; 可实现内存分配+类对象构造析构调用;

//来自boost库源码

template 
class object_pool: protected pool
{ //!
  ...

  protected:
    pool & store()
    { 
      return *this;
    }

  public:
    explicit object_pool(const size_type arg_next_size = 32, const size_type arg_max_size = 0)
    :
    pool(sizeof(T), arg_next_size, arg_max_size)
    { 
    }

    ~object_pool();

    // Returns 0 if out-of-memory.
    element_type * malloc BOOST_PREVENT_MACRO_SUBSTITUTION()
    { 
      return static_cast(store().ordered_malloc());
    }

    void free BOOST_PREVENT_MACRO_SUBSTITUTION(element_type * const chunk)
    { 
      store().ordered_free(chunk);
    }

    bool is_from(element_type * const chunk) const
    {
      return store().is_from(chunk);
    }

    element_type * construct()
    {
      element_type * const ret = (malloc)(); //先调用 element_type * malloc() 分配内存块;
      if (ret == 0)
        return ret;
      try { new (ret) element_type(); } //再在内存块上使用传入的参数调用类的构造函数;
      catch (...) { (free)(ret); throw; }
      return ret;
    }

#ifndef BOOST_NO_TEMPLATE_CV_REF_OVERLOADS
#   include 
#else
#   include 
#endif
#endif
    void destroy(element_type * const chunk)
    {
      chunk->~T(); //先调用析构
      (free)(chunk);//再归还内存块;
    }

    ...
};

使用示例:

{
		class demo_calss
		{
		public:
			int a,b,c;
			demo_calss(int x=1, int y=2, int z=3):a(x),b(y),c(z){}
		};

		// 对象内存池
		object_pool pl;

		demo_calss *p = pl.construct(5,6,7);
		cout << p->a << " " << p->b << " " << p->c << endl;
		pl.destroy(p);//调用类析构,同时归还内存块

		//到这里,对象内存池中还有一个空闲的内存块;

		//作用域结束,调用内存池析构真正释放所有内存;
	}

object_pool类的实现提供了实际用途内存池的关键,只需在其基础上增添一些内容即可实现一个可循环的内存池!!;

你可能感兴趣的:(c++,#,boost,c++,boost)