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

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

原文地址:https://www.cnblogs.com/yzdai/p/11442172.html

时间: 2024-10-25 02:52:35

内存对象管理器(基于数组和链表实现)的相关文章

基于数组实现的单链表(兼具Boost单元测试)

对于单链表,我们大多时候会用指针来实现(可参考基于指针实现的单链表).现在我们就来看看怎么用数组来实现单链表. 1. 定义单链表中结点的数据结构 1 typedef int ElementType; 2 class NodeType 3 { 4 public: 5 ElementType data; 6 int next; 7 }; 该结点包括了两个元素,其一是数据,另一个是指向下一个结点的"指针"(在这篇文章中实际上是指用于实现单链表的数组的下标.)  2. 定义一个的数组 1 co

数组和链表的区别

数组和链表的区别 数组是将元素在内存中连续存放,由于每个元素占用内存相同,可以通过下标迅速访问数组中任何元素.但是如果要在数组中增加一个元素,需要移动大量元素,在内存中空出一个元素的空间,然后将要增加的元素放在其中.同样的道理,如果想删除一个元素,同样需要移动大量元素去填掉被移动的元素.如果应用需要快速访问数据,很少或不插入和删除元素,就应该用数组. 链表恰好相反,链表中的元素在内存中不是顺序存储的,而是通过存在元素中的指针联系到一起.比如:上一个元素有个指针指到下一个元素,以此类推,直到最后一

程序设计基石与实践系列之类型提升、内存分配,数组转指针、打桩和矢量变换

英文出处:Peter Fa?ka: Guide to Advanced Programming in C C语言可用于系统编程.嵌入式系统中,同时也是其他应用程序可能的实现工具之一. 当你对计算机编程怀有强烈兴趣的时候,却对C语言不感冒,这种可能性不大.想全方位地理解C语言是一件极具挑战性的事. Peter Fa?ka 在2014年1月份写下了这篇长文,内容包括:类型提升.内存分配,数组转指针.显式内联.打桩(interpositioning)和矢量变换. 整型溢出和类型提升 多数C程序员以为,

数组还是链表?

1.什么是数组和链表? 数组和链表都是2这种不同的数据结构.数据结构可以简单理解为数据之间关系.数组是在内存上是一个联系的结构,而链表可以是一段不连续的结构.两者还有其他的区别: a.数组是静态分配内容,链表是动态分配内存. b.根据下标去获取结构里的第n个元素,数组的时间复杂读为O(1),链表的复杂度为O(n) c.删改第n个元素,数组的时间复杂度为O(n),链表的时间复杂读为O(1) 2.图形比较: 参考:http://blog.csdn.net/amork/article/details/

数组和链表区别

数组和链表的区别: 二者都属于一种数据结构从逻辑结构来看1. 数组必须事先定义固定的长度(元素个数),不能适应数据动态地增减的情况.当数据增加时,可能超出原先定义的元素个数:当数据减少时,造成内存浪费:数组可以根据下标直接存取.2. 链表动态地进行存储分配,可以适应数据动态地增减的情况,且可以方便地插入.删除数据项.(数组中插入.删除数据项时,需要移动其它数据项,非常繁琐)链表必须根据next指针找到下一个元素从内存存储来看      1. (静态)数组从栈中分配空间, 对于程序员方便快速,但是

程序员修炼之路-(2)线性表(上):数组与链表

1 两块基石 数组与链表构成各种数据结构的基石,是实现所有数据结构必不可少的元素. 1.1 数组 数组一般内置于编程语言中,直接通过索引(index)读写.索引一般为数字,有的语言甚至直接支持如字符串等其他类型的索引.在很多数据结构中都能看到数组的身影,例如字符串.动态数组.堆.栈和队列(用链表也可以,但用数组实现很高效)等. 1.2 链表 概念上都能理解,但实现起来还真有很多容易出错的地方. 实现细节 ?  表头(header):为什么要添加一个表头?因为有了表头,在第一个结点前添加结点或删除

数组和链表的区别以及数组和结构体的区别

1,数组和链表的区别? 链表和数组都叫可以叫做线性表, 数组又叫做顺序表,主要区别在于,顺序表是在内存中开辟一段连续的空间来存储数据,而且必须是相同类型的数据. 而链表是通过存在元素中的指针联系到一起的,每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域,链表既可以靠指针来连接多块不连续的的空间也可以用一段连续的空间, 在逻辑上形成一片连续的空间来存储数据. 两种数据结构各有各的好处,链表方便删除和插入,数组方便排序等. 数组从栈中分配空间, 对于程序员方便快速

数组与链表的优缺点

数组,在内存上给出了连续的空间.链表,内存地址上可以是不连续的,每个链表的节点包括原来的内存和下一个节点的信息(单向的一个,双向链表的话,会有两个). 数组优于链表的: 1.内存空间占用的少,因为链表节点会附加上一块或两块下一个节点的信息.但是数组在建立时就固定了.所以也有可能会因为建立的数组过大或不足引起内存上的问题. 2.数组内的数据可随机访问.但链表不具备随机访问性.这个很容易理解.数组在内存里是连续的空间.比如如果一个数组地址从100到200,且每个元素占用两个字节,那么100-200之

详解数组,链表和ADT

数组 先由一个例子复习一下数组的操作: class HighArray { private long[] a; private int nElems; //----------------------------------- public HighArray(int max) //构造函数 { a=new long[max]; nElems = 0; } //----------------------------------- public boolean find(long searchK