现在的位置: 首页 > 综合 > 正文

内存池版本3–单线程-可变大小对象的内存池

2013年01月20日 ⁄ 综合 ⁄ 共 2678字 ⁄ 字号 评论关闭
#include "stdafx.h"
#include
<windows.h>
#include
<MMSystem.h>
#include
<iostream>
using namespace std;

#pragma comment(lib, "winmm.lib")

class Foo
{
public:
Foo(
int a = 0, int b = 0):m(a), n(b) {}

private:
int m;
int n;
};

class MemoryChunk
{
public:
MemoryChunk(MemoryChunk
* next, size_t reqSize)
{
m_pNext
= next;
size_t chunkSize
= reqSize > DEFAULT_CHUNK_SIZE ? reqSize : DEFAULT_CHUNK_SIZE;
m_nChunkSize
= chunkSize;
m_pMem
= new char[m_nChunkSize];
m_nBytesAlreadyAllocated
= 0;
}

~MemoryChunk() {delete m_pMem;}

void* alloc(size_t size)
{
void* pAddr = (void*)((size_t)m_pMem + m_nBytesAlreadyAllocated);
m_nBytesAlreadyAllocated
+= size;
return pAddr;
}

void free(void* doomed)
{
//do nothing
//
}

MemoryChunk
* NextMemoryChunk() const {return m_pNext;}

size_t SpaceAvailiable()
const {return m_nChunkSize - m_nBytesAlreadyAllocated;}

enum{DEFAULT_CHUNK_SIZE = 4096};

private:
MemoryChunk
* m_pNext;
void* m_pMem;
size_t m_nChunkSize;
size_t m_nBytesAlreadyAllocated;
};

class ByteMemoryPool
{
public:
ByteMemoryPool(size_t initSize
= MemoryChunk::DEFAULT_CHUNK_SIZE)
{
m_chunkList
= 0; //must set to null
ExpandStorage(initSize);
}

~ByteMemoryPool()
{
MemoryChunk
* pChunk = m_chunkList;
while (pChunk)
{
m_chunkList
= pChunk->NextMemoryChunk();
delete pChunk;
pChunk
= m_chunkList;
}
}

void* alloc(size_t reqSize)
{
if (reqSize > m_chunkList->SpaceAvailiable())
{
ExpandStorage(reqSize);
}

return m_chunkList->alloc(reqSize);
}

void free(void* doomed)
{
m_chunkList
->free(doomed);
}

private:
MemoryChunk
* m_chunkList;

void ExpandStorage(size_t reqSize)
{
MemoryChunk
* pTmp = new MemoryChunk(m_chunkList, reqSize);
m_chunkList
= pTmp;
}
};


class Foo3
{
public:
Foo3(
int a= 0, int b = 0):m_x(a), m_y(b){}
void* operator new (size_t size)
{
if (m_pPool)
return m_pPool->alloc(size);
}

void operator delete(void* doomed)
{
if (m_pPool)
m_pPool
->free(doomed);
}

static void NewMemoryPool()
{
m_pPool
= new ByteMemoryPool();
}

static void DeleteMemoryPool()
{
delete m_pPool;
}

private:
int m_x;
int m_y;

static ByteMemoryPool* m_pPool;
};

ByteMemoryPool
* Foo3::m_pPool = 0;



int main()
{
DWORD time1, time2, deltaTime;
time1
= timeGetTime();
for (int i=0; i<500; ++i)
{
Foo
* ptrArray[1000];
for (int j=0; j<1000; ++j)
{
ptrArray[j]
= new Foo;
}

for (int j=0; j<1000; ++j)
{
delete ptrArray[j];
}
}

time2
= timeGetTime();
deltaTime
= time2- time1;
cout
<<deltaTime<<endl;

Foo3::NewMemoryPool();
time1
= timeGetTime();
for (int i=0; i<500; ++i)
{
Foo3
* ptrArray[1000];
for (int j=0; j<1000; ++j)
{
ptrArray[j]
= new Foo3;
}

for (int j=0; j<1000; ++j)
{
delete ptrArray[j];
}
}

time2
= timeGetTime();
Foo3::DeleteMemoryPool();
deltaTime
= time2- time1;
cout
<<deltaTime<<endl;

return 0;
}

  

// 1.只有内存块列表的第一个元素是可以用于分配内存的内存块。

// 2.在整个池的析构时会把所有内存归还给堆,而不是每次释放一个对象就将其内存归还给池或堆。

// 因为之前规定只有第一个块可用于分配,若把这些内存加到第一个快会出现内存不连续的问题;若

// 将这个释放的内存当做一个新块加到池的列表中那么就会出现有多个可以用于分配的内存块。

// 解决办法:可以在池中配置两个表,新加一个释放的内存块的链表,可以有多个可用于分配内存的块,

// 每次释放的内存都当做块加到这个链表中,当新分配内存时,优先遍历此表找是否有满足条件的块,若无、

// 再去分配的链表中去找满足条件的块,若无再分配。

//3.如果出现存储块用尽的情况,那么池就会调用ExpandStorage来分配一个新的内存块供使用。

抱歉!评论已关闭.