zoukankan      html  css  js  c++  java
  • C++ 封装私有堆(Private Heap)


      Private Heap 是 Windows 提供的一种内存内存机制,对于那些需要频繁分配和释放动态内存的应用程序来说,Private Heap 是提高应用程序性能的一大法宝,使用它能降低 new / malloc 的调用排队竞争以及内存空洞。Private Heap 的原理及应用的资料很多,这里就不一一介绍了,常用的 Private Heap API 有以下几个,具体介绍请参考帮助文档:

    复制代码
    HeapCreate();
    HeapDestroy();
    HeapAlloc();
    HeapReAlloc();
    HeapSize();
    HeapFree();
    HeapCompact();
    复制代码

      

      由于是 C 风格的 API,使用起来比较繁琐,因此本座在闲暇之余用 C++ 对这些 API 进行了封装,主要包括两个类:

    • CPrivateHeap:自动创建和销毁进程私有堆,每一个该类的对象都代表一个私有堆,所以该类对象的特点是: 一般生命周期都比较长,通常作为全局对象, 其他类的静态成员对象或者一些长生命周期类对象的成员。
    • CPrivateHeapBuffer<T>:在私有堆中自动分配和释放指定大小的内存,一般用于在函数体内分配和释放局部作用域的堆内存,从而避免对 CPrivateHeap::Alloc() 和 CPrivateHeap::Free() 的调用。
    复制代码
    #pragma once
    
    class CPrivateHeap
    {
    public:
        enum EnCreateOptions
        {
            CO_DEFAULT                = 0,
            CO_NO_SERIALIZE            = HEAP_NO_SERIALIZE,
            CO_GENERATE_EXCEPTIONS    = HEAP_GENERATE_EXCEPTIONS,
            CO_NOSERIALIZE_GENERATEEXCEPTIONS
                                    = HEAP_NO_SERIALIZE    |
                                      HEAP_GENERATE_EXCEPTIONS
        };
    
        enum EnAllocOptions
        {
            AO_DEFAULT                = 0,
            AO_ZERO_MEMORY            = HEAP_ZERO_MEMORY,
            AO_NO_SERIALIZE            = HEAP_NO_SERIALIZE,
            AO_GENERATE_EXCEPTIONS    = HEAP_GENERATE_EXCEPTIONS,
            AO_ZEROMEMORY_NOSERIALIZE
                                    = HEAP_ZERO_MEMORY    |
                                      HEAP_NO_SERIALIZE,
            AO_ZEROMEMORY_GENERATEEXCEPTIONS
                                    = HEAP_ZERO_MEMORY    |
                                      HEAP_GENERATE_EXCEPTIONS,
            AO_NOSERIALIZE_GENERATESEXCEPTIONS
                                    = HEAP_NO_SERIALIZE    |
                                      HEAP_GENERATE_EXCEPTIONS,
            AO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS
                                    = HEAP_ZERO_MEMORY    |
                                      HEAP_NO_SERIALIZE    |
                                      HEAP_GENERATE_EXCEPTIONS
        };
    
        enum EnReAllocOptions
        {
            RAO_DEFAULT                    = 0,
            RAO_ZERO_MEMORY                = HEAP_ZERO_MEMORY,
            RAO_NO_SERIALIZE            = HEAP_NO_SERIALIZE,
            RAO_GENERATE_EXCEPTIONS        = HEAP_GENERATE_EXCEPTIONS,
            RAO_REALLOC_IN_PLACE_ONLY    = HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_ZEROMEMORY_NOSERIALIZE
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_NO_SERIALIZE,
            RAO_ZEROMEMORY_GENERATEEXCEPTIONS
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_GENERATE_EXCEPTIONS,
            RAO_ZEROMEMORY_REALLOCINPLACEONLY
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_NOSERIALIZE_GENERATESEXCEPTIONS
                                        = HEAP_NO_SERIALIZE            |
                                          HEAP_GENERATE_EXCEPTIONS,
            RAO_NOSERIALIZE_REALLOCINPLACEONLY
                                        = HEAP_NO_SERIALIZE            |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_GENERATESEXCEPTIONS_REALLOCINPLACEONLY
                                        = HEAP_GENERATE_EXCEPTIONS    |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_NO_SERIALIZE            |
                                          HEAP_GENERATE_EXCEPTIONS,
            RAO_ZEROMEMORY_NOSERIALIZE_REALLOCINPLACEONLY
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_NO_SERIALIZE            |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_ZEROMEMORY_GENERATESEXCEPTIONS_REALLOCINPLACEONLY
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_GENERATE_EXCEPTIONS    |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_NOSERIALIZE_GENERATESEXCEPTIONS_REALLOCINPLACEONLY
                                        = HEAP_NO_SERIALIZE            |
                                          HEAP_GENERATE_EXCEPTIONS    |
                                          HEAP_REALLOC_IN_PLACE_ONLY,
            RAO_ZEROMEMORY_NOSERIALIZE_GENERATESEXCEPTIONS_REALLOCINPLACEONLY
                                        = HEAP_ZERO_MEMORY            |
                                          HEAP_NO_SERIALIZE            |
                                          HEAP_GENERATE_EXCEPTIONS    |
                                          HEAP_REALLOC_IN_PLACE_ONLY
        };
    
        enum EnSizeOptions
        {
            SO_DEFAULT        = 0,
            SO_NO_SERIALIZE    = HEAP_NO_SERIALIZE
        };
        
        enum EnFreeOptions
        {
            FO_DEFAULT        = 0,
            FO_NO_SERIALIZE    = HEAP_NO_SERIALIZE
        };
    
        enum EnCompactOptions
        {
            CPO_DEFAULT        = 0,
            CPO_NO_SERIALIZE    = HEAP_NO_SERIALIZE
        };
    
    public:
        PVOID Alloc(DWORD size, EnAllocOptions options = AO_DEFAULT)
            {return ::HeapAlloc(m_heap, options, size);}
    
        PVOID ReAlloc(PVOID pvmem, DWORD size, EnReAllocOptions options = RAO_DEFAULT)
            {return ::HeapReAlloc(m_heap, options, pvmem, size);}
    
        DWORD Size(PVOID pvmem, EnSizeOptions options = SO_DEFAULT)
            {return (DWORD)::HeapSize(m_heap, options, pvmem);}
    
        BOOL Free(PVOID pvmem, EnFreeOptions options = FO_DEFAULT)
            {return ::HeapFree(m_heap, options, pvmem);}
    
        DWORD Comapct(EnCompactOptions options = CPO_DEFAULT)
            {return (DWORD)::HeapCompact(m_heap, options);}
    
        BOOL IsValid() {return m_heap != NULL;}
    
    public:
        CPrivateHeap(EnCreateOptions options = CO_DEFAULT, DWORD initsize = 0, DWORD maxsize = 0)
            {m_heap = ::HeapCreate(options, initsize, maxsize);}
    
        ~CPrivateHeap() {if(IsValid()) ::HeapDestroy(m_heap);}
    
    private:
        CPrivateHeap(const CPrivateHeap&);
        CPrivateHeap operator = (const CPrivateHeap&);
    
    private:
        HANDLE    m_heap;
    };
    
    template<class T> 
    class CPrivateHeapBuffer
    {
    public:
        CPrivateHeapBuffer(    CPrivateHeap& heap, 
                            DWORD size = 0, 
                            CPrivateHeap::EnAllocOptions allocoptions    = CPrivateHeap::AO_DEFAULT, 
                            CPrivateHeap::EnFreeOptions freeoptions        = CPrivateHeap::FO_DEFAULT)
        : m_hpPrivate(heap)
        , m_opFree(freeoptions)
        {
            ASSERT(m_hpPrivate.IsValid());
            m_pvMemory = (T*)m_hpPrivate.Alloc(size * sizeof(T), allocoptions);
        }
    
        ~CPrivateHeapBuffer() {m_hpPrivate.Free(m_pvMemory, m_opFree);}
    
        T* ReAlloc(DWORD size, CPrivateHeap::EnReAllocOptions options = CPrivateHeap::RAO_DEFAULT)
            {return m_pvMemory = (T*)m_hpPrivate.ReAlloc(m_pvMemory, size * sizeof(T), options);}
    
        DWORD Size(CPrivateHeap::EnSizeOptions options = CPrivateHeap::SO_DEFAULT)
            {return m_hpPrivate.Size(m_pvMemory, options);}
    
        operator T* () const {return m_pvMemory;}
    
    private:
        CPrivateHeapBuffer(const CPrivateHeapBuffer&);
        CPrivateHeapBuffer operator = (const CPrivateHeapBuffer&);
    
    private:
        CPrivateHeap&                m_hpPrivate;
        T*                            m_pvMemory;
        CPrivateHeap::EnFreeOptions m_opFree;
    };
    
    typedef CPrivateHeapBuffer<BYTE>    CPrivateHeapByteBuffer;
    typedef CPrivateHeapBuffer<TCHAR>    CPrivateHeapStrBuffer;
    复制代码

      上述代码看起来挺复杂,但使用起来却是异常简单的,请看下面的使用示例:

    复制代码
    // 全局可见的 Heap
    CPrivateHeap g_heap;
    
    class MyClass
    {
    private:
        // 与类实例生命周期一致的 Heap
        CPrivateHeap m_heap;
    
        // 仅类内部可见的 Heap
        static CPrivateHeap sm_heap;
    
    public:
        void test_m_eap()
        {
            // 无需显式释放堆内存
            CPrivateHeapStrBuffer buff(m_heap, 32);
            lstrcpy(buff, _T("失败乃成功之母"));
            DWORD size = buff.Size();
            buff.ReAlloc(40 * sizeof(TCHAR));
            size = buff.Size();
            std::cout << (TCHAR*)buff << '
    ';
        }
    
        static void test_sm_eap()
        {
            CPrivateHeapStrBuffer buff(sm_heap, 32);
            lstrcpy(buff, _T("失败乃成功之母"));
            DWORD size = buff.Size();
            buff.ReAlloc(40 * sizeof(TCHAR));
            size = buff.Size();
            std::cout << (TCHAR*)buff << '
    ';
        }
    };
    
    void test_g_heap()
    {
        // 如果不使用 CPrivateHeapBuffer<T> 来封装堆内存
    
        ASSERT(g_heap.IsValid());
        TCHAR* pch    = (TCHAR*)g_heap.Alloc(32 * sizeof(TCHAR));
        lstrcpy(pch, _T("失败乃成功之母"));
        DWORD size = g_heap.Size(pch);
        g_heap.ReAlloc(pch, 40 * sizeof(TCHAR));
        size = g_heap.Size(pch);
        std::cout << pch << '
    ';
    
        // 需要显式释放堆内存
        g_heap.Free(pch);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        test_g_heap();
    
        MyClass::test_sm_eap();
        
        MyClass c;
        c.test_m_eap();
    
        return 0;
    }
    复制代码
  • 相关阅读:
    解决Altera家的ROM仿真数据一直为0
    解决sublime text3 中文字符乱码
    sublime3添加verilog自动补全代码段
    慢腾腾的Quartus prime16.0加快编译速度
    Quartus prime16.0 与modelsim ae 联调
    JTAG基础知识
    Quartus prime 16.0 中通过JTAG固化程序
    FPGA功能仿真,门级仿真,后仿真的区别
    testbench中$display查看例化model里面信号方法以及$realtime用法
    PHP 批量移动文件改名
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318614.html
Copyright © 2011-2022 走看看