内存对象管理器(基于数组和链表实现)

Posted yzdai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内存对象管理器(基于数组和链表实现)相关的知识,希望对你有一定的参考价值。

1.1 数组的特点

  • 连续的内存空间分配并且顺序存储数据,使用之前需要先分配数组个数;
  • 可以通过下标进行访问修改数据,时间复杂度为O(1);
  • 空间效率不是很好,不能随意修改数组大小;
  • 增删数据需要内存拷贝

 

1.2 链表的特点

技术图片

  • 内存空间分配是分散的,非连续的存储数据;
  • 不能通过下标直接访问,查找的时间复杂度为O(n);
  • 增删元素,只需要改变前后指针;

1.3 基于数组和指针实现的对象管理器

技术图片

结合了数组和链表的优点,可以O(1)查找元素,O(1)增删元素;

需要预分配内存;

 

 

2.代码实现(C++)

/**
*@file ObjAllocator
*@author jasonxiong
*@date 2009-12-09
*@version 1.0
*@brief CObj对象分配类,即新版本的idxobj
*
*    (1)一般用于大型对象的内存分配
*/

#ifndef __OBJ_ALLOCATOR_HPP__
#define __OBJ_ALLOCATOR_HPP__

#include <stdio.h>

namespace ServerLib


typedef enum enmObjAllocType

    EOAT_ALLOC_BY_SELF = 0,          //!<对象内存由ObjAllocator自已动态分配
    EOAT_ALLOC_BY_SHARED_MEMORY = 1, //!<对象内存由共享内存分配
 ENMOBJALLOCTYPE;

class CObj;

typedef enum enmIdxUseFlag

    EIUF_FREE = 0, //!<该对象未被使用
    EIUF_USED = 1, //!<该对象已被使用
 ENMIDXUSEFLAG;

//!索引类,仅在CObjAllocator中使用,外层一般不用
class CIdx

public:
    CIdx();
    ~CIdx();

public:
    //!初始化函数
    int Initialize();

    //!将对象设置为未使用
    inline void SetFree()
    
        m_iUseFlag = EIUF_FREE;
    

    //!将对象设置为已使用
    inline void SetUsed()
    
        m_iUseFlag = EIUF_USED;
    

    //!判断对象是否已被使用
    inline int IsUsed() const
    
        return m_iUseFlag == EIUF_USED;
    

    //!获取所在链表下一个索引
    inline int GetNextIdx() const
    
        return m_iNextIdx;
    

    //!设置所在链表下一个索引
    inline void SetNextIdx(int iIdx)
    
        m_iNextIdx = iIdx;
    

    //!获取所在链表上一个索引
    inline int GetPrevIdx() const
    
        return m_iPrevIdx;
    

    //!设置所在链表上一个索引
    inline void SetPrevIdx(int iIdx)
    
        m_iPrevIdx = iIdx;
    

    //!获取指向的对象
    inline CObj *GetAttachedObj() const
    
        return m_pAttachedObj;
    

    //!设置指向的对象
    inline void SetAttachedObj(CObj *pObj)
    
        m_pAttachedObj = pObj;
    

private:
    int m_iNextIdx;       //!<对象索引块链表指针,指向后一个闲/忙索引
    int m_iPrevIdx;       //!<对象索引块链表指针,指向前一个闲/忙索引
    int m_iUseFlag;       //!<该对象是否已经被使用标志
    CObj *m_pAttachedObj; //!<所指向的对象指针
;

typedef CObj *(*Function_CreateObj)(void *);

class CObjAllocator

private:
    //默认构造函数,不允许上层自行调用
    CObjAllocator();

public:
    CObjAllocator(size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj);
    ~CObjAllocator();

    /**
    *使用共享内存创建ObjAllocator
    *@param[in] pszKeyFileName 共享内存Attach的文件名
    *@param[in] ucKeyPrjID 共享内存的工程ID
    *@param[in] uiObjSize 对象大小
    *@param[in] iObjCount 对象个数
    *@param[in]
    *@return 0 success
    */
    static CObjAllocator *CreateBySharedMemory(const char *pszKeyFileName,
                                               const unsigned char ucKeyPrjID,
                                               size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj);

    /**
    *指定内存指针来创建CObjAllocator
    *@param[in] pszMemoryAddress 指定的内存
    *@param[in] uiMemorySize 内存大小
    *@param[in] uiObjSize 对象大小
    *@param[in] iObjCount 对象个数
    *@param[in] pfCreateObj 创建CObj对象的函数,默认可以用DECLARE_DYN中的CreateObject
    *@return 0 success
    */
    static CObjAllocator *CreateByGivenMemory(char *pszMemoryAddress, size_t uiMemorySize,
                                              size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj);

    static size_t CountSize(size_t uiObjSize, int iObjCount);

    static CObjAllocator *ResumeByGivenMemory(char *pszMemoryAddress,
                                              size_t uiMemorySize, size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj);

public:
    //!初始化函数,将数据清空
    int Initialize();

    //!创建一个对象,成功返回对象ID,失败返回小于0的值
    int CreateObject();

    //!创建一个对象, 并指定其ID,成功返回对象ID,失败返回小于0的值
    int CreateObjectByID(int iID);

    //!根据对象ID销毁一个对象,成功返回0
    int DestroyObject(int iObjectID);

    //!根据ObjectID返回对象,必须保证该对象已被使用
    CObj *GetObj(int iObjectID);

    //!根据ObjectID返回索引
    CIdx *GetIdx(int iObjectID);

    //!获取已用对象链表头索引
    inline int GetUsedHead() const
    
        return m_iUsedHeadIdx;
    

    //!获取空闲对象链表头索引
    inline int GetFreeHead() const
    
        return m_iFreeHeadIdx;
    

    //获取已用对象个数
    inline int GetUsedCount() const
    
        return m_iUsedCount;
    

    //获取空闲对象个数
    inline int GetFreeCount() const
    
        return m_iObjCount - m_iUsedCount;
    

    //!在接口返回错误时,调用这个函数获取错误号
    inline int GetErrorNO() const
    
        return m_iErrorNO;
    

    //获取对象分配类型
    inline int GetObjAllocType() const
    
        return m_shObjAllocType;
    

    //!获取下一个对象
    CObj *GetNextObj(int iObjectID);

    //!设置对象初始化指针
    inline void SetCreateObjFunc(Function_CreateObj pfCreateObjFunc)
    
        m_pfCreateObjFunc = pfCreateObjFunc;
    

private:
    //!设置错误号
    inline void SetErrorNO(int iErrorNO)
    
        m_iErrorNO = iErrorNO;
    

private:
    //这几个对象只有在构造函数时确定,后面不会更改
    short m_shObjAllocType;               //!<对象分配类型
    size_t m_uiObjSize;                   //!<单个对象
    int m_iObjCount;                      //!<最多分配的对象个数
    CIdx *m_astIdxs;                      //!<索引数组,用于管理对象链表
    CObj *m_pstObjBuffer;                 //!<分配的对象内存
    Function_CreateObj m_pfCreateObjFunc; //!<在内存上创建CObj对象的函数,每个子类需要自己实现

    //以下的对象会更改,调用Initialize初始化
    int m_iErrorNO;     //!<错误码
    int m_iFreeHeadIdx; //!<空闲对象链表头索引
    int m_iFreeTailIdx; //!<空闲对象链表尾索引
    int m_iUsedHeadIdx; //!<已用对象链表头索引
    int m_iUsedCount;   //!<已用对象个数
;

//!基本对象类
class CObj

public:
    CObj() 
    virtual ~CObj() 

public:
    //!对象的初始化函数,在CObjAllocator创建对象时会调用,所以子类一定要实现
    virtual int Initialize() = 0;

    //!显示对象函数,可重载
    virtual int Show() const
    
        return 0;
    

    //!获取对象ID
    inline int GetObjectID() const
    
        return m_iObjectID;
    

    //!设置对象ID
    inline void SetObjectID(int iObjectID)
    
        m_iObjectID = iObjectID;
    

    virtual int Resume()
    
        return 0;
    

private:
    int m_iObjectID; //!对象ID,即在CObjAllocator中的数组下标

    friend int CObjAllocator::Initialize(); //!<在这个函数中需要直接赋值m_iObjectID,所以设为友元
;

#define DECLARE_DYN                                               public:                                                               void *operator new(size_t uiSize, const void *pThis) throw();     static CObj *CreateObject(void *pMem);

#define IMPLEMENT_DYN(class_name)                                                void *class_name::operator new(size_t uiSize, const void *pThis) throw()                                                                                     if (!pThis)                                                                                                                                                  return NULL;                                                                                                                                                                                                                      return (void *)pThis;                                                                                                                                                                                                             CObj *class_name::CreateObject(void *pMem)                                                                                                                   return (CObj *)new (pMem) class_name;                                    

 // namespace ServerLib

#endif //__OBJ_ALLOCATOR_HPP__
///:~


/**
*@file ObjAllocator.cpp
*@author jasonxiong
*@date 2009-12-14
*@version 1.0
*@brief 对象分配类的实现文件
*
*
*/

#include <assert.h>

#include "ErrorDef.hpp"
#include "ObjAllocator.hpp"
#include "SharedMemory.hpp"

using namespace ServerLib;

CIdx::CIdx()

    Initialize();


CIdx::~CIdx()



int CIdx::Initialize()

    m_iNextIdx = -1;
    m_iPrevIdx = -1;
    m_iUseFlag = 0;
    m_pAttachedObj = NULL;

    return 0;


CObjAllocator::CObjAllocator()



//void* CObjAllocator::operator new(unsigned int uiSize, const void* pThis) throw()
//
//    if(!pThis)
//    
//        return NULL;
//    
//
//    return (void*)pThis;
//

CObjAllocator::CObjAllocator(size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj)

    __ASSERT_AND_LOG(uiObjSize > 0 && iObjCount > 0 && pfCreateObj);

    m_shObjAllocType = EOAT_ALLOC_BY_SELF;
    m_iObjCount = iObjCount;
    m_uiObjSize = uiObjSize;
    m_pfCreateObjFunc = pfCreateObj;

    m_astIdxs = new CIdx[m_iObjCount];
    size_t uiObjMemorySize = uiObjSize * iObjCount;
    char *pstObjMem = new char[uiObjMemorySize];
    m_pstObjBuffer = (CObj *)pstObjMem;

    __ASSERT_AND_LOG(m_astIdxs && m_pstObjBuffer);

    Initialize();


size_t CObjAllocator::CountSize(size_t uiObjSize, int iObjCount)

    return sizeof(CObjAllocator) + uiObjSize * iObjCount + iObjCount * sizeof(CIdx);


CObjAllocator *CObjAllocator::CreateByGivenMemory(char *pszMemoryAddress, size_t uiMemorySize, size_t uiObjSize,
                                                  int iObjCount, Function_CreateObj pfCreateObj)

    if (pszMemoryAddress == NULL || uiObjSize <= 0 || iObjCount <= 0 || pfCreateObj == NULL)
    
        TRACESVR("%p, %d, %d, %p.\\n", pszMemoryAddress, (int)uiObjSize, iObjCount, pfCreateObj);
        return NULL;
    

    size_t uiSharedMemorySize = sizeof(CObjAllocator) + uiObjSize * iObjCount +
                                iObjCount * sizeof(CIdx);

    if (uiSharedMemorySize > uiMemorySize)
    
        TRACESVR("ObjAllocator: alloc size %lu > sh size %lu.\\n", (unsigned long)uiSharedMemorySize, (unsigned long)uiMemorySize);
        return NULL;
    

    //在指定的内存地址上分配CObjAllocator
    CObjAllocator *pstObjAllocator = (CObjAllocator *)pszMemoryAddress;

    if (!pstObjAllocator)
    
        TRACESVR("ObjAllocator: pstObjAllocator is NULL.\\n");
        return NULL;
    

    pstObjAllocator->m_uiObjSize = uiObjSize;
    pstObjAllocator->m_iObjCount = iObjCount;
    pstObjAllocator->m_pfCreateObjFunc = pfCreateObj;
    pstObjAllocator->m_shObjAllocType = EOAT_ALLOC_BY_SHARED_MEMORY;
    pstObjAllocator->m_astIdxs = (CIdx *)((unsigned char *)pszMemoryAddress + sizeof(CObjAllocator));
    pstObjAllocator->m_pstObjBuffer = (CObj *)((unsigned char *)pszMemoryAddress + sizeof(CObjAllocator) + iObjCount * sizeof(CIdx));

    pstObjAllocator->Initialize();

    return pstObjAllocator;


CObjAllocator *CObjAllocator::ResumeByGivenMemory(char *pszMemoryAddress,
                                                  size_t uiMemorySize, size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj)

    if ((NULL == pszMemoryAddress) || (uiObjSize <= 0) || (iObjCount <= 0))
    
        return NULL;
    

    size_t uiSharedMemorySize = sizeof(CObjAllocator) + uiObjSize * iObjCount + sizeof(CIdx) * iObjCount;

    if (uiSharedMemorySize > uiMemorySize)
    
        return NULL;
    

    CObjAllocator *pstObjAllocator = (CObjAllocator *)pszMemoryAddress;

    if ((pstObjAllocator->m_uiObjSize != uiObjSize) || (pstObjAllocator->m_iObjCount != iObjCount))
    
        return NULL;
    

    pstObjAllocator->m_shObjAllocType = EOAT_ALLOC_BY_SHARED_MEMORY;
    pstObjAllocator->m_astIdxs = (CIdx *)((unsigned char *)pszMemoryAddress + sizeof(CObjAllocator));
    pstObjAllocator->m_pstObjBuffer = (CObj *)((unsigned char *)pszMemoryAddress + sizeof(CObjAllocator) + iObjCount * sizeof(CIdx));

    int i;

    // 重新绑定obj和idx
    for (i = 0; i < iObjCount; ++i)
    
        // 调用placement-new, 恢复类的虚函数表.
        CObj *pstObj = (*pfCreateObj)((unsigned char *)pstObjAllocator->m_pstObjBuffer + uiObjSize * i);

        __ASSERT_AND_LOG(pstObj->GetObjectID() == i);

        pstObjAllocator->m_astIdxs[i].SetAttachedObj(pstObj);
    

    pstObjAllocator->SetCreateObjFunc(pfCreateObj);
    return pstObjAllocator;


CObjAllocator *CObjAllocator::CreateBySharedMemory(const char *pszKeyFileName, const unsigned char ucKeyPrjID,
                                                   size_t uiObjSize, int iObjCount, Function_CreateObj pfCreateObj)

    if (pszKeyFileName == NULL || uiObjSize <= 0 || iObjCount <= 0 || pfCreateObj == NULL)
    
        return NULL;
    

    CSharedMemory stSharedMemory;
    size_t uiSharedMemorySize = sizeof(CObjAllocator) + uiObjSize * iObjCount +
                                iObjCount * sizeof(CIdx);

    int iRet = stSharedMemory.CreateShmSegment(pszKeyFileName, ucKeyPrjID,
                                               (int)uiSharedMemorySize);

    if (iRet)
    
        return NULL;
    

    //在共享内存的地址上分配CObjAllocator
    CObjAllocator *pstObjAllocator = (CObjAllocator *)stSharedMemory.GetFreeMemoryAddress();

    if (!pstObjAllocator)
    
        return NULL;
    

    pstObjAllocator->m_uiObjSize = uiObjSize;
    pstObjAllocator->m_iObjCount = iObjCount;
    pstObjAllocator->m_pfCreateObjFunc = pfCreateObj;
    pstObjAllocator->m_shObjAllocType = EOAT_ALLOC_BY_SHARED_MEMORY;
    pstObjAllocator->m_astIdxs = (CIdx *)((unsigned char *)stSharedMemory.GetFreeMemoryAddress() + sizeof(CObjAllocator));
    pstObjAllocator->m_pstObjBuffer = (CObj *)((unsigned char *)stSharedMemory.GetFreeMemoryAddress() +
                                               sizeof(CObjAllocator) + iObjCount * sizeof(CIdx));

    return pstObjAllocator;


CObjAllocator::~CObjAllocator()

    if (m_shObjAllocType == EOAT_ALLOC_BY_SELF)
    
        if (m_astIdxs)
        
            delete[] m_astIdxs;
            m_astIdxs = NULL;
        

        if (m_pstObjBuffer)
        
            char *pstObjMem = (char *)m_pstObjBuffer;
            delete[] pstObjMem;
            m_pstObjBuffer = NULL;
        
    


int CObjAllocator::Initialize()

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);

        return -1;
    

    if (m_iObjCount <= 0)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_COUNT);

        return -2;
    

    //初始化索引数组
    int i;
    for (i = 0; i < m_iObjCount; ++i)
    
        m_astIdxs[i].Initialize();
        m_astIdxs[i].SetPrevIdx(i - 1);
        m_astIdxs[i].SetNextIdx(i + 1);
    

    m_astIdxs[m_iObjCount - 1].SetNextIdx(-1);

    //初始化对象数组
    for (i = 0; i < m_iObjCount; ++i)
    
        CObj *pstObj = (*m_pfCreateObjFunc)((unsigned char *)m_pstObjBuffer + m_uiObjSize * i);
        pstObj->m_iObjectID = i;
        m_astIdxs[i].SetAttachedObj(pstObj);
    

    m_iErrorNO = 0;
    m_iFreeHeadIdx = 0;
    m_iFreeTailIdx = m_iObjCount - 1;
    m_iUsedHeadIdx = -1;
    m_iUsedCount = 0;

    return 0;


int CObjAllocator::CreateObject()

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);
        return -1;
    

    if (m_iUsedCount >= m_iObjCount)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__OBJ_IS_FULL);
        return -2;
    

    if (m_iFreeHeadIdx < 0 || m_iFreeHeadIdx >= m_iObjCount)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);
        return -3;
    

    //修改空闲链表
    int iCurIdx = m_iFreeHeadIdx;
    m_iFreeHeadIdx = m_astIdxs[m_iFreeHeadIdx].GetNextIdx();

    if (m_iFreeHeadIdx >= 0)
    
        m_astIdxs[m_iFreeHeadIdx].SetPrevIdx(-1);
    

    if (iCurIdx == m_iFreeTailIdx)
    
        m_iFreeTailIdx = -1;
    

    //挂到使用链表
    m_astIdxs[iCurIdx].SetUsed();
    m_astIdxs[iCurIdx].SetNextIdx(m_iUsedHeadIdx);
    m_astIdxs[iCurIdx].SetPrevIdx(-1);

    if (m_iUsedHeadIdx >= 0)
    
        m_astIdxs[m_iUsedHeadIdx].SetPrevIdx(iCurIdx);
    

    //初始化对象
    m_iUsedHeadIdx = iCurIdx;

    CObj *pstObj = m_astIdxs[iCurIdx].GetAttachedObj();
    if (NULL == pstObj)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);
        return -4;
    

#ifdef OBJ_MEMSET_ON_CREATE
    memset(pstObj, 0, m_uiObjSize);
    (*m_pfCreateObjFunc)((unsigned char *)pstObj);
    pstObj->SetObjectID(iCurIdx);
#endif

    pstObj->Initialize();
    ++m_iUsedCount;

    __ASSERT_AND_LOG(pstObj->GetObjectID() == iCurIdx);

    return iCurIdx;


int CObjAllocator::CreateObjectByID(int iID)

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);

        return -1;
    

    if (iID < 0 || iID >= m_iObjCount)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);

        return -2;
    

    if (m_astIdxs[iID].IsUsed())
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);

        return -3;
    

    //修改空闲链表
    int iCurIdx = iID;
    int iPrevIdx = m_astIdxs[iCurIdx].GetPrevIdx();
    int iNextIdx = m_astIdxs[iCurIdx].GetNextIdx();

    if (iPrevIdx >= 0)
    
        m_astIdxs[iPrevIdx].SetNextIdx(iNextIdx);
    

    if (iNextIdx >= 0)
    
        m_astIdxs[iNextIdx].SetPrevIdx(iPrevIdx);
    

    if (iCurIdx == m_iFreeHeadIdx)
    
        m_iFreeHeadIdx = iNextIdx;
    

    if (iCurIdx == m_iFreeTailIdx)
    
        m_iFreeTailIdx = -1;
    

    //挂到使用链表
    m_astIdxs[iCurIdx].SetUsed();
    m_astIdxs[iCurIdx].SetNextIdx(m_iUsedHeadIdx);
    m_astIdxs[iCurIdx].SetPrevIdx(-1);

    if (m_iUsedHeadIdx >= 0)
    
        m_astIdxs[m_iUsedHeadIdx].SetPrevIdx(iCurIdx);
    

    m_iUsedHeadIdx = iCurIdx; // add by cary

    CObj *pstObj = m_astIdxs[iCurIdx].GetAttachedObj();

#ifdef OBJ_MEMSET_ON_CREATE
    memset(pstObj, 0, m_uiObjSize);
    (*m_pfCreateObjFunc)((unsigned char *)pstObj);
    pstObj->SetObjectID(iCurIdx);
#endif

    pstObj->Initialize();
    ++m_iUsedCount;

    __ASSERT_AND_LOG(pstObj->GetObjectID() == iCurIdx);

    return iCurIdx;


int CObjAllocator::DestroyObject(int iObjectID)

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);

        return -1;
    

    if (iObjectID >= m_iObjCount || iObjectID < 0 || m_iObjCount <= 0)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);

        return -2;
    

    if (!m_astIdxs[iObjectID].IsUsed())
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__DESTROY_FREE_OBJ);

        return -3;
    

    //从已用链表中删除
    int iCurIdx = iObjectID;
    int iPrevIdx = m_astIdxs[iCurIdx].GetPrevIdx();
    int iNextIdx = m_astIdxs[iCurIdx].GetNextIdx();

    if (iPrevIdx >= 0)
    
        m_astIdxs[iPrevIdx].SetNextIdx(iNextIdx);
    

    if (iNextIdx >= 0)
    
        m_astIdxs[iNextIdx].SetPrevIdx(iPrevIdx);
    

    if (iCurIdx == m_iUsedHeadIdx)
    
        m_iUsedHeadIdx = iNextIdx;
    

    //挂入空闲链表尾部
    m_astIdxs[iObjectID].SetFree();
    m_astIdxs[iObjectID].SetPrevIdx(m_iFreeTailIdx);
    m_astIdxs[iObjectID].SetNextIdx(-1);

    if (m_iFreeHeadIdx == -1)
    
        m_iFreeHeadIdx = iCurIdx;
    

    if (m_iFreeTailIdx >= 0)
    
        m_astIdxs[m_iFreeTailIdx].SetNextIdx(iCurIdx);
    

    m_iFreeTailIdx = iCurIdx;
    --m_iUsedCount;

    return 0;


CObj *CObjAllocator::GetObj(int iObjectID)

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);

        return NULL;
    

    if (iObjectID < 0 || iObjectID >= m_iObjCount)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);

        return NULL;
    

    if (!m_astIdxs[iObjectID].IsUsed())
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__GET_FREE_OBJ);

        return NULL;
    

    return m_astIdxs[iObjectID].GetAttachedObj();


CIdx *CObjAllocator::GetIdx(int iObjectID)

    if (m_pstObjBuffer == NULL || m_astIdxs == NULL)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__NULL_POINTER);

        return NULL;
    

    if (iObjectID < 0 || iObjectID >= m_iObjCount)
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__INVALID_OBJ_INDEX);

        return NULL;
    

    if (!m_astIdxs[iObjectID].IsUsed())
    
        SetErrorNO(EEN_OBJ_ALLOCATOR__GET_FREE_OBJ);

        return NULL;
    

    return &m_astIdxs[iObjectID];


CObj *CObjAllocator::GetNextObj(int iObjectID)

    CIdx *pIdx = GetIdx(iObjectID);

    if (!pIdx)
    
        return NULL;
    

    int iNextObjIdx = pIdx->GetNextIdx();

    return GetObj(iNextObjIdx);

 

源码地址:https://github.com/dai543103/ServerFramework-1/blob/master/001_ServerLib/BaseLibs/ObjAllocator.hpp

以上是关于内存对象管理器(基于数组和链表实现)的主要内容,如果未能解决你的问题,请参考以下文章

设计模式—迭代器Iterator模式

HashMap实现原理

浅谈HashMap实现原理

江哥带你玩转C语言 - 16-内存管理和链表

江哥带你玩转C语言 - 16-内存管理和链表

面试测试岗(社招)