MemoryPool 实作

#ifndef _KOK_MEMORYPOOL_H_
#define _KOK_MEMORYPOOL_H_

#pragma once

#include <cstddef>
#include "StaticAssert.h"
#include <new>

#define NULL 0

namespace KOK
{
    typedef void (*FnDestroy)(void* p);

    struct ArrayHeader
    {
        size_t nArrayCount;
    };

    template <class T, bool b = TypeTraits::IsClass<T>::value>
    struct FnTrait
    {


        static void Destory(void* p)
        {
            ((T*)p)->~T();
        }

        static void DestoryArray(void* p)
        {
            ArrayHeader* pHeader = (ArrayHeader*)p;
            T* pElem = (T*)(pHeader + 1);
            while(pHeader->nArrayCount)
            {
                pElem->~T();
                pElem++;
                pHeader->nArrayCount--;
            }
        }

    };

    template <class T>
    struct FnTrait<T, false>
    {
        static FnDestroy Destory;
        static FnDestroy DestoryArray;
    };

    template <class T>
    FnDestroy FnTrait<T, false>::Destory = NULL;

    template <class T>
    FnDestroy FnTrait<T, false>::DestoryArray = NULL;

    class MemoryPool
    {
        struct DestroyNode
        {
            FnDestroy fnDestroy;
            DestroyNode* pNodePrev;
        };

        struct MemPage
        {
            void* pPos;
            void* pLast;
            MemPage* pPagePrev;
        };


    protected:
        inline void* AllocAux(size_t nSize) const { return malloc(nSize); }
        inline void FreeAux(void* p) const { return free(p); }
        MemPage* AllocNewPage(size_t nSize);

    public:
        void* Alloc(size_t nSize, FnDestroy fnDestroy);
        void* AllocArray(size_t nSize, size_t nArrayCount, FnDestroy fnDestroy);
        inline MemoryPool() { m_nMaxSize_ = PAGE_MAX_SIZE; m_nAlign_ = sizeof(char*); m_pCurPage_ = NULL; m_pCurDestroyNode_ = NULL; }
        inline MemoryPool(size_t nSize, size_t nAlign = sizeof(char*)) { m_nMaxSize_ = nSize; m_nAlign_ = nAlign; m_pCurPage_ = NULL; m_pCurDestroyNode_ = NULL; }
        void Reset();
        void Clear();
        inline ~MemoryPool() { Clear(); }

    private:
        static const unsigned int PAGE_MAX_SIZE = 1*1024*1024;
        size_t m_nMaxSize_;
        MemPage* m_pCurPage_;
        DestroyNode* m_pCurDestroyNode_;
        size_t m_nAlign_;

    };

    void* MemoryPool::Alloc(size_t nSize, FnDestroy fnDestroy)
    {
        if(fnDestroy != NULL)
            nSize += sizeof(DestroyNode);

        void* pTemp;
        nSize = (nSize + (m_nAlign_ - 1)) & ~(m_nAlign_ - 1); // align

        if(m_pCurPage_ == NULL)
        {
            m_pCurPage_ = AllocNewPage(nSize);
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }
        else if(nSize <= (char*)m_pCurPage_->pLast - (char*)m_pCurPage_->pPos)
        {
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }
        else if(nSize <= (char*)m_pCurPage_->pPagePrev->pLast - (char*)m_pCurPage_->pPagePrev->pPos)
        {
            pTemp = m_pCurPage_->pPagePrev->pPos;
            m_pCurPage_->pPagePrev->pPos = (void*)((char*)m_pCurPage_->pPagePrev->pPos + nSize);
        }
        else
        {
            MemPage* pNewPage = AllocNewPage(nSize);
            pNewPage->pPagePrev = m_pCurPage_;
            m_pCurPage_ = pNewPage;
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }

        if(fnDestroy != NULL)
        {
            DestroyNode* pDesTemp = (DestroyNode*)pTemp;
            pTemp = pDesTemp + 1;
            pDesTemp->fnDestroy = fnDestroy;
            pDesTemp->pNodePrev = m_pCurDestroyNode_;
            m_pCurDestroyNode_ = pDesTemp;
        }
        return pTemp;
    }

    void* MemoryPool::AllocArray(size_t nSize, size_t nArrayCount, FnDestroy fnDestroy)
    {
        if(fnDestroy != NULL)
        {
            nSize += sizeof(DestroyNode);
            nSize += sizeof(ArrayHeader);
        }

        void* pTemp;
        nSize = (nSize + (m_nAlign_ - 1)) & ~(m_nAlign_ - 1); // align

        if(m_pCurPage_ == NULL)
        {
            m_pCurPage_ = AllocNewPage(nSize);
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }
        else if(nSize <= (char*)m_pCurPage_->pLast - (char*)m_pCurPage_->pPos)
        {
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }
        else if(nSize <= (char*)m_pCurPage_->pPagePrev->pLast - (char*)m_pCurPage_->pPagePrev->pPos)
        {
            pTemp = m_pCurPage_->pPagePrev->pPos;
            m_pCurPage_->pPagePrev->pPos = (void*)((char*)m_pCurPage_->pPagePrev->pPos + nSize);
        }
        else
        {
            MemPage* pNewPage = AllocNewPage(nSize);
            pNewPage->pPagePrev = m_pCurPage_;
            m_pCurPage_ = pNewPage;
            pTemp = m_pCurPage_->pPos;
            m_pCurPage_->pPos = (void*)((char*)m_pCurPage_->pPos + nSize);
        }

        if(fnDestroy != NULL)
        {
            DestroyNode* pDesTemp = (DestroyNode*)pTemp;
            pTemp = pDesTemp + 1;
            pDesTemp->fnDestroy = fnDestroy;
            pDesTemp->pNodePrev = m_pCurDestroyNode_;
            m_pCurDestroyNode_ = pDesTemp;
        }
        return pTemp;
    }

    MemoryPool::MemPage* MemoryPool::AllocNewPage(size_t nSize)
    {
        nSize = nSize > m_nMaxSize_ ? (nSize + sizeof(MemPage)) : (m_nMaxSize_ + sizeof(MemPage));
        MemPage* pPageTemp = (MemPage*)AllocAux(nSize);
        pPageTemp->pPagePrev = NULL;
        pPageTemp->pPos = pPageTemp + sizeof(MemPage);
        pPageTemp->pLast = pPageTemp + nSize;
        return pPageTemp;
    }

    void MemoryPool::Reset()
    {
        char* pStart;
        while(m_pCurDestroyNode_ != NULL)
        {
            m_pCurDestroyNode_->fnDestroy(m_pCurDestroyNode_ + 1);
            m_pCurDestroyNode_ = m_pCurDestroyNode_->pNodePrev;
        }

        while(m_pCurPage_ != NULL)
        {
            pStart = (char*)m_pCurPage_;
            memset(pStart + sizeof(MemPage), 0, (char*)(m_pCurPage_->pLast) - pStart);
            m_pCurPage_->pPos = pStart + sizeof(MemPage);
            m_pCurPage_ = m_pCurPage_->pPagePrev;
        }
    }

    void MemoryPool::Clear()
    {
        char* pStart;
        while(m_pCurDestroyNode_ != NULL)
        {
            m_pCurDestroyNode_->fnDestroy(m_pCurDestroyNode_ + 1);
            m_pCurDestroyNode_ = m_pCurDestroyNode_->pNodePrev;
        }

        while(m_pCurPage_ != NULL)
        {
            MemPage* pPageTemp = m_pCurPage_->pPagePrev;
            FreeAux(m_pCurPage_);
            m_pCurPage_ = pPageTemp;
        }
    }

    //
    //  Global Function
    //
    template <class T>
    inline T* NewType(MemoryPool* memPool)
    {
        T* pAlloc = (T*)memPool->Alloc(sizeof(T), FnTrait<T>::Destory);
        return new(pAlloc) T;
    }

    template <class T>
    inline T* NewArray(MemoryPool* memPool, const size_t n)
    {
        if(n == 0)
            return NULL;

        T* pAlloc = (T*)memPool->AllocArray(sizeof(T), n, FnTrait<T>::DestoryArray);
        return new(pAlloc) T[n];
    }

#define NEW(PMEMPOOL, T) new((PMEMPOOL)->Alloc(sizeof(T), FnTrait<T>::Destory)) T
#define NEWARRAY(PMEMPOOL, T, N) (N) == 0 ? NULL : new((PMEMPOOL)->AllocArray(sizeof(T)*(N), (N), FnTrait<T>::DestoryArray)) T[(N)]

}
#endif

 

#ifndef _KOK_STATICASSERT_H_
#define _KOK_STATICASSERT_H_

#pragma once

namespace KOK
{
    struct TypeTraits
    {
        template<typename T> struct IsArray {  static const bool value = false; };

        template<typename T, int N> struct IsArray<T[N]> {  static const bool value = true; };

        template<typename T> struct IsPointer {  static const bool value = false; };

        template<typename T> struct IsPointer<T*> {  static const bool value = true; };

        template<typename T> struct IsRef {  static const bool value = false; };

        template<typename T> struct IsRef<T&> {  static const bool value = true; };

        template<typename T> struct IsConst {  static const bool value = false; };

        template<typename T> struct IsConst<const T> {  static const bool value = true; };

        template<typename T> struct IsConstRef {  static const bool value = false; };

        template<typename T> struct IsConstRef<const T&> {  static const bool value = true; };

        template<typename T> struct IsConstPointer {  static const bool value = false; };

        template<typename T> struct IsConstPointer<const T*> {  static const bool value = true; };

        template<typename T> struct IsInteger {  static const bool value = false; };

        template<> struct IsInteger<int> {  static const bool value = true; };

        template<typename T> struct IsFloat {  static const bool value = false; };

        template<> struct IsFloat<float> {  static const bool value = true; };

        template<typename T> struct IsLong {  static const bool value = false; };

        template<> struct IsLong<long> {  static const bool value = true; };

        template<typename T> struct IsDouble {  static const bool value = false; };

        template<> struct IsDouble<double> {  static const bool value = true; };


        template<typename T> struct IsClass
        {
        private:
            template<typename U> struct IsClassImpl
            {
                struct RightType { char store; };
                struct WrongType { char store[2]; };
                template<typename K> //in order to explict template so add it
                static WrongType Func(...);
                template<typename K>
                static RightType Func(void (K::*)(void));

                static const bool value = (sizeof(Func<U>(0)) == sizeof(RightType));
            };
        public:
            static const bool value = IsClassImpl<T>::value;
        };


        /* template<typename T> struct is_enum
        { 
        private:
        template<typename U> struct is_enum_impl
        {
        struct right_type { char store; };
        struct wrong_type { char store[2]; };
        template<typename K>
        static wrong_type func(...);
        template<typename K>
        static right_type func(K::);

        static const bool value = (sizeof(func<U>(0)) == sizeof(right_type));
        };
        public:
        static const bool value = is_class_impl<T>::value;
        };*/

        template<typename T> struct is_union
        {};

    };
}

#endif

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值