C++ 封装私有堆(Private Heap)

来源:互联网 发布:商陆花软件视频教程 编辑:程序博客网 时间:2024/05/21 08:55


  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 onceclass 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;
复制代码

 

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

复制代码
// 全局可见的 HeapCPrivateHeap 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 << '\n';    }    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 << '\n';    }};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 << '\n';    // 需要显式释放堆内存    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;}
复制代码
原创粉丝点击