• 内存池与内存块


    #include <iostream>
    using namespace std;

    constexpr int MEMORYPOOL_ALIGNMENT = 8;                        //对齐长度

    // 内存块
    template<typename _T>
    struct MemoryBlock {
        int          nSize;                     //内存块大小,以字节为单位
        int          nFree;                     //内存块剩余可分配单位
        int          nFirst;                    //首个剩余单位序号
        MemoryBlock* pNext;                     //指向下一个内存块的指针
        char         aData[1];                  //内存空间开始位置标记

        //constructor
        MemoryBlock(int nUnitSize,               // 存储单位大小,sizeof T
                    int nUnitAmount) :              // 内存块规模,以 存储单位 为单位计算
                    nSize(nUnitAmount * nUnitSize), nFree(nUnitAmount - 1), nFirst(1), pNext(nullptr) {
                        //第一个单位在调用构造函数时分配,故nFree需要减1
                        //下一个可分配单位序号记录于当前单元的前两个字节
                        char *ppDate = aData;
                        cout << "the head ptr of memory ppDate = " << (int)*ppDate << endl;
                        for(int i = 1; i < nUnitAmount; ++i) {
                            //在 当前存储单位存储下一个可分配单位的序号
                            (*(uint16_t*)ppDate) = i;//short --- 16
                            cout << "the next available of memory is :" << (int)*ppDate << endl;
                            ppDate += nUnitSize; //指向下一个单位
                        }
                        cout << "===========================call MemoryBlock constructor ";
                    }

        // overload 
        void* operator new(size_t, int nUnitSize, int nUnitAmount) {
            //内存空间长度为memoryBlock对象加存储空间总长度
            return ::operator new(sizeof(MemoryBlock) + nUnitAmount * nUnitSize);
        }

        void operator delete(void *pBlock) {
            ::operator delete(pBlock);
            cout << "================================call MemoryBlock destructor ";
        }

    };

    // 内存池
    template<typename _T>
    struct MemoryPool {
        int             nInitSize; //第一次分配大小
        int             nGrowSize; //增量大小
        int             nUnitSize; // 存储单位大小
        MemoryBlock<_T> *pBlock;

        MemoryPool(int _nGrowSize = 10, int _nInitSize = 3) 
            : nInitSize(_nInitSize), nGrowSize(_nGrowSize), pBlock(nullptr), nUnitSize(sizeof(_T)) {
            cout << "==========================call MemoryPool constructor ";
            //存储块大小调整
            auto _size = sizeof(_T);
            if(_size > 4) {
                nUnitSize = (_size + MEMORYPOOL_ALIGNMENT - 1) & ~(MEMORYPOOL_ALIGNMENT - 1);
            }
            else if(_size < 2) {
                nUnitSize = 2;
            }
            else
                nUnitSize = 4;
        }

        ~MemoryPool() {
            MemoryBlock<_T> * pMyBlock = pBlock;
            while(pMyBlock != nullptr) {
                pMyBlock = pMyBlock->pNext;
                delete pMyBlock;
            }
            cout << "================================call MemoryPool destructor ";
        }

        void *allocate(size_t num) { //typename Allocator<_T>::const_pointer hint = 0
            for(int i = 0; i < num; ++i) {
                if(pBlock == nullptr) {
                    //create memoryBlock
                    pBlock = (MemoryBlock<_T>*) new (nUnitSize, nInitSize) MemoryBlock<_T>(nUnitSize, nInitSize);

                    return (void *)pBlock->aData;
                }
                //找到合适的内存块
                MemoryBlock<_T> *pMyBlock = pBlock;
                while(pMyBlock != nullptr && pMyBlock->nFree == 0) pMyBlock = pMyBlock->pNext;
                if(pMyBlock != nullptr) {
                    cout << "找到内存空间, first = " << pMyBlock->nFirst << endl;
                    char *pFree = pMyBlock->aData + pMyBlock->nFirst * nUnitSize;
                    pMyBlock->nFirst = *((uint16_t *)pFree);
                    pMyBlock->nFree--;
                    return (void *)pFree;
                }
                else {
                    //没有找到,说明内存块已经用完
                    if(nGrowSize == 0) return NULL;
                    cout << "allocate new memoryBlock ";
                    pMyBlock = (MemoryBlock<_T>*) new (nUnitSize, nGrowSize) MemoryBlock<_T> (nUnitSize, nGrowSize);
                    //失败返回
                    if(pMyBlock == nullptr) return NULL;
                    //成功的话插入链表
                    pMyBlock->pNext = pBlock;
                    pBlock = pMyBlock;
                    return (void *)pMyBlock->aData;
                }
            }



        }

        void free(void *pFree) {
            cout << "relese room ";
            //找到内存块
            MemoryBlock<_T> * pMyBlock = pBlock;
            MemoryBlock<_T> * preBlock = nullptr;
            while (pMyBlock != nullptr && (pBlock->aData > pFree || pMyBlock->aData + pMyBlock->nSize)) {
                preBlock = pMyBlock;
                pMyBlock = pMyBlock->next;
            }
            //
            if(pMyBlock != nullptr) {
                //修改数组链表
                *((uint16_t*)pFree) = pMyBlock->nFirst;
                pMyBlock->nFirst = (uint16_t)((uint32_t)pFree - (uint32_t)pMyBlock->aData) / nUnitSize;
                pMyBlock->nFree++;
            
                //是否需要向OS释放内存
                if(pMyBlock->nSize == pMyBlock->nFree * nUnitSize) {
                    //delete node
                    delete pMyBlock;
                }
                else {
                    //将block插入队首
                    preBlock = pMyBlock->pNext;
                    pMyBlock->pNext = nullptr;
                    pBlock = pMyBlock;
                }
            } 
        }

    };


    class User {
        int s;
        double s1;
        double s3;
    public:
        User(int x) : s(x) {
            cout << "*********************call User constructor ";
        }

        int get() const { return s; };
        ~User() {
            cout << "************************call User destructor ";
        }
    };

    int main() {
        
        MemoryPool<User> pool;
        User *dp1 = (User *)pool.allocate(1);
        cout << "dp1 = " << dp1 << endl;
        new (dp1) User (1111);
        cout << "the value of object is " << dp1->get() << endl;



        User *dp2 = (User *)pool.allocate(1);
        cout << "dp2 = " << dp2 << endl;
        new (dp2) User (2222);
        cout << "the value of object is " << dp2->get() << endl;


        User *dp3 = (User *)pool.allocate(1);
        cout << "dp3 = " << dp3 << endl;
        new (dp3) User (3333);
        cout << "the value of object is " << dp3->get() << endl;


        User *dp4 = (User *)pool.allocate(1);
        cout << "dp4 = " << dp4 << endl;
        new (dp4) User (4444);
        cout << "the value of object is " << dp4->get() << endl;


        User *dp5 = (User *)pool.allocate(1);
        cout << "dp5 = " << dp5 << endl;
        new (dp5) User (5555);
        cout << "the value of object is " << dp5->get() << endl;






        
        return 0;
    }



  • 相关阅读:
    ASP.NET跨页面传值技巧总结
    C#向Sql Server中插入记录时单引号的处理 使用存储过程 .NET教程,C#语言
    在.net平台上如何创建和使用web 服务(C#)
    使用母版页时内容页如何使用css和javascript
    HTML ID和Name属性的区别
    c++/c#中的转义符
    SendMessage 启动屏幕保护程序_2
    sendmessage WM_PAINT带背景的窗体
    UPPERERR.txt
    With do 简化代码语句
  • 原文地址:https://www.cnblogs.com/MasterYan576356467/p/12181530.html
Copyright © 2020-2023  润新知