首页 > 其他分享 >pool

pool

时间:2024-11-01 19:46:54浏览次数:3  
标签:malloc void free 内存 type pool

boost.pool

boost.pool库基于简单分隔存储的思想实现了一个快速、紧凑的内存池
不仅能够管理大量对象,还可以用作STL的内存分配器,在需要大量分配或释放小对象时效率很高,且不需要考虑delete

包含4个组成部分

  • 简单pool
  • 分配类实例object_pool
  • 单件内存池singleton_pool
  • 用于标准库pool_alloc

pool

最简单和最容易使用的内存池类,返回一个简单数据类型POD的内存指针,位于命名空间boost

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

类原型

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* chunk, size_type n);
    void ordered_free(void* chunk, size_type n);

    bool release_memory();
    bool purge_memory();
};

模板类型参数UserAllocator使用默认的内存分配器,基于new[]delete[]实现

malloc()ordered_malloc()从内存池中分配内存块,大小由构造函数参数requested_size指定,若分配失败会返回空指针,不抛出异常

malloc()从内存池中任意分配一个内存块,而ordered_malloc()在分配的同时合并空闲块链表,带参数的ordered_malloc()可以连续分配n块内存

is_from()测试内存块是否属于当前内存池

一般情况下,内存池会自动管理内存分配,不需要调用free(),除非用户认为内存池空间不足,必须先释放一定的内存

release_memory()释放内存池中所有未被分配的内存,已分配的不受影响
purge_memory()强制释放内存池持有的所有内存,析构函数就是调用的该函数

示例如下:

int main(){
    pool<> p(sizeof(int)); // 一个可分配int的内存池
    int* p1= static_cast<int*>(p.malloc()); // 转换void*
    if(p1!=nullptr){
    }
    assert(p1.is_from(p));

    p.free(p1);
    for(int i=0; i<100; ++i){ // 连续分配大量的内存
        p.ordered_malloc(10);
    }
}

pool只能用于普通数据类型的内存池,不能应用于复杂类型和对象,因为其只分配内存,不构造对象

object_pool

应用于类实例的内存池,功能与pool类似,但其会在析构时对所有已分配的内存块调用析构函数

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

类原型

template<typename T, typename UserAllocator>
class object_pool:protected pool<UserAllocator>{
public:
    typedef T element_type;
public:
    object_pool();
    ~object_pool();

    element_type* malloc();
    void free(element_type* p);
    bool is_from(element_type* p)const;

    element_type* construct(...);
    void destroy(element_type* p);
};

object_pool的模板类型参数T指定要分配的元素类型,要求其析构函数不抛出异常
一旦指定了类型,object_pool对象就不能再用于分配其他类型

construct()有多个重载形式,先调用malloc()分配内存,再根据参数调用类的构造函数
destroy()先调用对象的析构函数,再用free()释放内存块

malloc()free()表示分配和释放一块类型为T*的内存块
只有在当前内存池中分配的内存块才能被free()释放
这两个函数被调用时不调用类构造函数和析构函数,操作的是原始内存块,里面的值是未定义的

示例如下:

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

int main(){
    object_pool<demo> p;
    auto p1= p.malloc();
    assert(p.is_from(p1));

    // p1指向的内存未初始化
    assert(p->a!=1 || p->b!=2 || p->c!=3);

    p1= p.construct(7,8,9);
    assert(p->a==7);

    object_pool<string> pstr;
    for(int i=0; i<10; ++i){
        string* p2= pstr.construct("hello object_pool");
        std::cout<<*p2<<std::endl;
    }
}

默认情况下,使用object_pool只能接收3个参数来创建对象
使用C++标准的可变参数模板解决该问题

template<typename T, typename ... Args>
inline typename T::element_type* construct(T& t, Args&& ... args){
    typename T::element_type* mem= t.malloc();
    assert(mem!=0);

    new (mem) typename T::element_type(std::forward<Args>(args)...); // 完美转发
    return mem;
}

// 使用
object_pool<demo> p;
auto p1= construct(p, 1,2,3,4);

singleton_pool

与pool类似,用于分配POD,但是该类对象是一个单件

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

默认使用boost.thread库提供线程安全,所以需要将其链接boost_thread库
若不使用多线程,可在头文件前定义BOOST_POOL_NO_MT

类原型

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();
};

模板类型参数Tag用于标记不同的单件,可以是空类,甚至可以只进行声明
参数RequestedSize等同于pool中的requested_size,用来指示内存块大小

因为singleton_pool是单件,所有其声明周期与整个程序一致,除非手动释放

示例如下:

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();
}

标签:malloc,void,free,内存,type,pool
From: https://www.cnblogs.com/sgqmax/p/18521153

相关文章

  • UNIVERSITY OFLIVERPOOLDepartment of Electrical Engineering and Electronics
    UNIVERSITYOFLIVERPOOLDepartmentofElectricalEngineeringandElectronicscontactmeonhelp-assignmentcontactmeonhelp-assignmentcontactmeonhelp-assignmentAssignmentOverviewInstantiationandmanipulationofgeometricalobjectsissignificant......
  • 线程池ThreadPoolExecutor配合callable获得线程执行结果
    此处记录使用callable创建线程,使用线程池执行,看下是否有进行线程复用并且FutureTask返回结果线程创建publicclassMyCallableBakeUserimplementsCallable<String>{privateinta;publicMyCallableBakeUser(inta){this.a=a;}@Overrid......
  • 使用ThreadPoolExecutor线程池消化线程执行代码
    此处记录一个使用ThreadPoolExecutor线程池的demo线程代码publicclassExcutorRunnableimplementsRunnable{@Overridepublicvoidrun(){System.out.println(Thread.currentThread().getName()+":线程执行666");try{Thread.......
  • .NET中的线程池ThreadPool(链接)
    微软推荐在.NET中使用多线程开发时,都使用线程池,下面这篇微软文档介绍了.NET中的线程池类ThreadPool:ThreadPoolClass注意上面文档中的这句话:Thereisonethreadpoolperprocess.也就是说,每个.NET进程(process)中有一个线程池,线程池在每个.NET进程中只有一个,一个.NET进程中......
  • ScheduledThreadPoolExecutor的介绍与使用
    ScheduledThreadPoolExecutor是Java中的一个类,它继承自ThreadPoolExecutor,并实现了ScheduledExecutorService接口。这个类主要用于在给定的延迟之后或周期性地执行任务,是处理定时任务的一个强大工具。一、主要特点线程池大小固定:ScheduledThreadPoolExecutor的线程池大小......
  • 鸿蒙编程江湖:深入理解TaskPool和Worker的并发任务执行
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。鸿蒙系统提供了两种并发能力:TaskPool和......
  • 在Windows操作系统中,配置系统服务和检查服务的状态是确保系统正常运行的关键步骤。以
    在Windows操作系统中,配置系统服务和检查服务的状态是确保系统正常运行的关键步骤。以下是关于系统服务、PrintSpooler服务的工作状态、身份增强校验失败和Guest账户未激活的详细说明:1.系统服务概述Windows系统服务是后台运行的程序,用于执行系统管理任务或支持应用程序的运行。......
  • Tomcat10JdbcPoolDemo
    packagecom.renguanyu.demo;importjava.sql.Connection;importjava.sql.ResultSet;importjava.sql.Statement;importorg.apache.tomcat.jdbc.pool.DataSource;importorg.apache.tomcat.jdbc.pool.PoolProperties;publicclassTomcat10JdbcPoolDemo{ public......
  • Python中的pool.map函数:高效处理数据与计算任务
    在Python中,map()函数是一个非常实用的工具,它能对序列(如列表、元组等)进行映射操作,将一个函数作用于序列中的每个元素,并将结果组成一个新的序列返回。在一些大规模的数据处理和计算任务中,我们往往需要对大量数据进行高效的处理。这时,map()函数就显得尤为重要,而它的一个实现——pool.......
  • [20241013]sqlplus spool与文件覆盖.txt
    [20241013]sqlplusspool与文件覆盖.txt--//这个问题在8月份遇到的问题,我发现在sqlplus下spoola.sql文件,并没有在当前目录产生a.sql文件,后来我发现建立在环境变量--//ORACLE_PATH定义的目录下,当时以为自己打开多个会话,没有注意自己工作的当前目录。事后我测试,问题视乎消失了,我再......