SMemoryChunk.h
#ifndef __SMEMORYCHUNK_H__
#define
__SMEMORYCHUNK_H__
typedef unsigned
char
TByte ;
struct
SMemoryChunk { TByte
*
Data;
//
数据
std::size_t DataSize;
//
该内存块的总大小
std::size_t UsedSize;
//
实际使用的大小
bool
IsAllocationChunk; SMemoryChunk
*
Next;
//
指向链表中下一个块的指针。
};
#endif
IMemoryBlock.h
#ifndef __IMEMORYBLOCK_H__
#define
__IMEMORYBLOCK_H__
class
IMemoryBlock {
public
:
virtual
~
IMemoryBlock() {};
virtual
void
*
GetMemory(
const
std::size_t
&
sMemorySize)
=
0
;
virtual
void
FreeMemory(
void
*
ptrMemoryBlock,
const
std::size_t
&
sMemoryBlockSize)
=
0
;
};
#endif
CMemoryPool.h
#ifndef __CMEMORYPOOL_H__
#define
__CMEMORYPOOL_H__
#include
"
IMemoryBlock.h
"
#include
"
SMemoryChunk.h
"
static
const
std::size_t DEFAULT_MEMORY_POOL_SIZE
=
1000
;
//
初始内存池的大小
static
const
std::size_t DEFAULT_MEMORY_CHUNK_SIZE
=
128
;
//
Chunk的大小
static
const
std::size_t DEFAULT_MEMORY_SIZE_TO_ALLOCATE
=
DEFAULT_MEMORY_CHUNK_SIZE
*
2
;
class
CMemoryPool :
public
IMemoryBlock {
public
: CMemoryPool(
const
std::size_t
&
sInitialMemoryPoolSize
=
DEFAULT_MEMORY_POOL_SIZE,
const
std::size_t
&
sMemoryChunkSize
=
DEFAULT_MEMORY_CHUNK_SIZE,
const
std::size_t
&
sMinimalMemorySizeToAllocate
=
DEFAULT_MEMORY_SIZE_TO_ALLOCATE,
bool
bSetMemoryData
=
false
);
virtual
~
CMemoryPool();
//
从内存池中申请内存
virtual
void
*
GetMemory(
const
std::size_t
&
sMemorySize);
virtual
void
FreeMemory(
void
*
ptrMemoryBlock,
const
std::size_t
&
sMemoryBlockSize);
private
:
//
申请内存OS
bool
AllocateMemory(
const
std::size_t
&
sMemorySize);
void
FreeAllAllocatedMemory(); SMemoryChunk
*
FindChunkHoldingPointerTo(
void
*
ptrMemoryBlock);
void
FreeChunks(SMemoryChunk
*
ptrChunk);
//
计算可以分多少块
unsigned
int
CalculateNeededChunks(
const
std::size_t
&
sMemorySize);
//
计算内存池最合适的大小
std::size_t CMemoryPool::CalculateBestMemoryBlockSize(
const
std::size_t
&
sRequestedMemoryBlockSize);
//
建立链表.每个结点Data指针指向内存池中的内存地址
bool
LinkChunksToData(SMemoryChunk
*
ptrNewChunks, unsigned
int
uiChunkCount, TByte
*
ptrNewMemBlock);
//
重新计算块(Chunk)的大小1024--896--768--640--512------------
bool
RecalcChunkMemorySize(SMemoryChunk
*
ptrChunk, unsigned
int
uiChunkCount); SMemoryChunk
*
SetChunkDefaults(SMemoryChunk
*
ptrChunk);
//
搜索链表找到一个能够持有被申请大小的内存块(Chunk).如果它返回NULL,那么在内存池中没有可用的内存
SMemoryChunk
*
FindChunkSuitableToHoldMemory(
const
std::size_t
&
sMemorySize);
std::size_t MaxValue(
const
std::size_t
&
sValueA,
const
std::size_t
&
sValueB)
const
;
void
SetMemoryChunkValues(SMemoryChunk
*
ptrChunk,
const
std::size_t
&
sMemBlockSize);
SMemoryChunk
*
SkipChunks(SMemoryChunk
*
ptrStartChunk, unsigned
int
uiChunksToSkip);
void
DeallocateAllChunks();
private
:
SMemoryChunk
*
m_ptrFirstChunk; SMemoryChunk
*
m_ptrLastChunk; SMemoryChunk
*
m_ptrCursorChunk;
std::size_t m_sTotalMemoryPoolSize;
//
内存池的总大小
std::size_t m_sUsedMemoryPoolSize;
//
以使用内存的大小
std::size_t m_sFreeMemoryPoolSize;
//
可用内存的大小
std::size_t m_sMemoryChunkSize;
//
块(Chunk)的大小
unsigned
int
m_uiMemoryChunkCount;
//
块(Chunk)的数量
unsigned
int
m_uiObjectCount;
bool
m_bSetMemoryData ; std::size_t m_sMinimalMemorySizeToAllocate;
};
#endif
CMemoryPool.cpp
#include
"
stdafx.h
"
#include
"
CMemorypool.h
"
#include
<
math.h
>
#include
<
assert.h
>
static
const
int
FREEED_MEMORY_CONTENT
=
0xAA
;
//
填充释放的内存
static
const
int
NEW_ALLOCATED_MEMORY_CONTENT
=
0xFF
;
CMemoryPool::CMemoryPool(
const
std::size_t
&
sInitialMemoryPoolSize,
const
std::size_t
&
sMemoryChunkSize,
const
std::size_t
&
sMinimalMemorySizeToAllocate,
bool
bSetMemoryData) { m_ptrFirstChunk
=
NULL; m_ptrLastChunk
=
NULL; m_ptrCursorChunk
=
NULL;
m_sTotalMemoryPoolSize
=
0
; m_sUsedMemoryPoolSize
=
0
; m_sFreeMemoryPoolSize
=
0
;
m_sMemoryChunkSize
=
sMemoryChunkSize; m_uiMemoryChunkCount
=
0
; m_uiObjectCount
=
0
;
m_bSetMemoryData
=
!
bSetMemoryData; m_sMinimalMemorySizeToAllocate
=
sMinimalMemorySizeToAllocate;
AllocateMemory(sInitialMemoryPoolSize); }
CMemoryPool::
~
CMemoryPool() { FreeAllAllocatedMemory(); DeallocateAllChunks();
assert((m_uiObjectCount
==
0
)
&&
"
警告:内存-泄露:你没有释放全部申请的内存
"
); }
void
CMemoryPool::FreeAllAllocatedMemory() { SMemoryChunk
*
ptrChunk
=
m_ptrFirstChunk;
while
(ptrChunk) {
if
(ptrChunk
->
IsAllocationChunk) { free(((
void
*
) (ptrChunk
->
Data))); } ptrChunk
=
ptrChunk
->
Next; } }
void
CMemoryPool::DeallocateAllChunks() { SMemoryChunk
*
ptrChunk
=
m_ptrFirstChunk; SMemoryChunk
*
ptrChunkToDelete
=
NULL;
while
(ptrChunk) {
if
(ptrChunk
->
IsAllocationChunk) {
if
(ptrChunkToDelete) { free(((
void
*
) ptrChunkToDelete)); } ptrChunkToDelete
=
ptrChunk; } ptrChunk
=
ptrChunk
->
Next; } }
void
*
CMemoryPool::GetMemory(
const
std::size_t
&
sMemorySize) { std::size_t sBestMemBlockSize
=
CalculateBestMemoryBlockSize(sMemorySize); SMemoryChunk
*
ptrChunk
=
NULL;
while
(
!
ptrChunk) {
ptrChunk
=
FindChunkSuitableToHoldMemory(sBestMemBlockSize);
//
ptrChunk等于NULL表示内存池内存不够用
if
(
!
ptrChunk) { sBestMemBlockSize
=
MaxValue(sBestMemBlockSize, CalculateBestMemoryBlockSize(m_sMinimalMemorySizeToAllocate));
//
从OS申请更多的内存
AllocateMemory(sBestMemBlockSize); } }
//
下面是找到可用的块(Chunk)代码
m_sUsedMemoryPoolSize
+=
sBestMemBlockSize; m_sFreeMemoryPoolSize
-=
sBestMemBlockSize; m_uiObjectCount
++
;
//
标记该块(Chunk)已用
SetMemoryChunkValues(ptrChunk, sBestMemBlockSize);
return
((
void
*
) ptrChunk
->
Data); }
void
CMemoryPool::FreeMemory(
void
*
ptrMemoryBlock,
const
std::size_t
&
sMemoryBlockSize) { SMemoryChunk
*
ptrChunk
=
FindChunkHoldingPointerTo(ptrMemoryBlock);
if
(ptrChunk) { FreeChunks(ptrChunk); }
else
{ assert(
false
&&
"
ERROR : Requested Pointer not in Memory Pool
"
); } assert((m_uiObjectCount
>
0
)
&&
"
ERROR : Request to delete more Memory then allocated.
"
); m_uiObjectCount
--
;
}
void
CMemoryPool::FreeChunks(SMemoryChunk
*
ptrChunk) {
SMemoryChunk
*
ptrCurrentChunk
=
ptrChunk ; unsigned
int
uiChunkCount
=
CalculateNeededChunks(ptrCurrentChunk
->
UsedSize);
for
(unsigned
int
i
=
0
; i
<
uiChunkCount; i
++
) {
if
(ptrCurrentChunk) {
if
(m_bSetMemoryData) { memset(((
void
*
) ptrCurrentChunk
->
Data), FREEED_MEMORY_CONTENT, m_sMemoryChunkSize) ; }
ptrCurrentChunk
->
UsedSize
=
0
;
m_sUsedMemoryPoolSize
-=
m_sMemoryChunkSize; ptrCurrentChunk
=
ptrCurrentChunk
->
Next; } } }
SMemoryChunk
*
CMemoryPool::FindChunkHoldingPointerTo(
void
*
ptrMemoryBlock) { SMemoryChunk
*
ptrTempChunk
=
m_ptrFirstChunk;
while
(ptrTempChunk) {
if
(ptrTempChunk
->
Data
==
((TByte
*
) ptrMemoryBlock)) {
break
; } ptrTempChunk
=
ptrTempChunk
->
Next; }
return
ptrTempChunk; }
bool
CMemoryPool::AllocateMemory(
const
std::size_t
&
sMemorySize) {
//
计算可以分多少块(1000 / 128 = 8)
unsigned
int
uiNeededChunks
=
CalculateNeededChunks(sMemorySize);
//
当内存池的初始大小为1000字节,块(Chunk)大小128字节,分8块还差24字节.怎么办?
//
解决方案:多申请24字节
std::size_t sBestMemBlockSize
=
CalculateBestMemoryBlockSize(sMemorySize);
//
向OS申请内存
TByte
*
ptrNewMemBlock
=
(TByte
*
) malloc(sBestMemBlockSize);
//
分配一个结构体SmemoryChunk的数组来管理内存块
SMemoryChunk
*
ptrNewChunks
=
(SMemoryChunk
*
) malloc((uiNeededChunks
*
sizeof
(SMemoryChunk)));
m_sTotalMemoryPoolSize
+=
sBestMemBlockSize; m_sFreeMemoryPoolSize
+=
sBestMemBlockSize; m_uiMemoryChunkCount
+=
uiNeededChunks;
if
(m_bSetMemoryData) { memset(((
void
*
) ptrNewMemBlock), NEW_ALLOCATED_MEMORY_CONTENT, sBestMemBlockSize); }
return
LinkChunksToData(ptrNewChunks, uiNeededChunks, ptrNewMemBlock);
}
unsigned
int
CMemoryPool::CalculateNeededChunks(
const
std::size_t
&
sMemorySize) {
float
f
=
(
float
) (((
float
)sMemorySize)
/
((
float
)m_sMemoryChunkSize));
return
((unsigned
int
) ceil(f)); }
std::size_t CMemoryPool::CalculateBestMemoryBlockSize(
const
std::size_t
&
sRequestedMemoryBlockSize) { unsigned
int
uiNeededChunks
=
CalculateNeededChunks(sRequestedMemoryBlockSize);
return
std::size_t((uiNeededChunks
*
m_sMemoryChunkSize)); }
bool
CMemoryPool::LinkChunksToData(SMemoryChunk
*
ptrNewChunks, unsigned
int
uiChunkCount, TByte
*
ptrNewMemBlock) {
SMemoryChunk
*
ptrNewChunk
=
NULL; unsigned
int
uiMemOffSet
=
0
;
bool
bAllocationChunkAssigned
=
false
;
for
(unsigned
int
i
=
0
; i
<
uiChunkCount; i
++
) {
//
建立链表
if
(
!
m_ptrFirstChunk) { m_ptrFirstChunk
=
SetChunkDefaults(
&
(ptrNewChunks[
0
])); m_ptrLastChunk
=
m_ptrFirstChunk; m_ptrCursorChunk
=
m_ptrFirstChunk; }
else
{ ptrNewChunk
=
SetChunkDefaults(
&
(ptrNewChunks[i])); m_ptrLastChunk
->
Next
=
ptrNewChunk; m_ptrLastChunk
=
ptrNewChunk; }
//
根据块(Chunk)的大小计算下一块的内存偏移地址
uiMemOffSet
=
(i
*
((unsigned
int
) m_sMemoryChunkSize));
//
结点指向内存偏移地址
m_ptrLastChunk
->
Data
=
&
(ptrNewMemBlock[uiMemOffSet]);
if
(
!
bAllocationChunkAssigned) { m_ptrLastChunk
->
IsAllocationChunk
=
true
; bAllocationChunkAssigned
=
true
; } }
return
RecalcChunkMemorySize(m_ptrFirstChunk, m_uiMemoryChunkCount);
}
bool
CMemoryPool::RecalcChunkMemorySize(SMemoryChunk
*
ptrChunk, unsigned
int
uiChunkCount) { unsigned
int
uiMemOffSet
=
0
;
for
(unsigned
int
i
=
0
; i
<
uiChunkCount; i
++
) {
if
(ptrChunk) { uiMemOffSet
=
(i
*
((unsigned
int
) m_sMemoryChunkSize)) ; ptrChunk
->
DataSize
=
(((unsigned
int
) m_sTotalMemoryPoolSize)
-
uiMemOffSet); ptrChunk
=
ptrChunk
->
Next; }
else
{ assert(
false
&&
"
Error : ptrChunk == NULL
"
);
return
false
; } }
return
true
; }
SMemoryChunk
*
CMemoryPool::SetChunkDefaults(SMemoryChunk
*
ptrChunk) {
if
(ptrChunk) { ptrChunk
->
Data
=
NULL; ptrChunk
->
DataSize
=
0
; ptrChunk
->
UsedSize
=
0
; ptrChunk
->
IsAllocationChunk
=
false
; ptrChunk
->
Next
=
NULL; }
return
ptrChunk; }
//
这里还没看明白
SMemoryChunk
*
CMemoryPool::FindChunkSuitableToHoldMemory(
const
std::size_t
&
sMemorySize) { unsigned
int
uiChunksToSkip
=
0
;
bool
bContinueSearch
=
true
; SMemoryChunk
*
ptrChunk
=
m_ptrCursorChunk;
for
(unsigned
int
i
=
0
; i
<
m_uiMemoryChunkCount; i
++
) {
if
(ptrChunk) {
if
(ptrChunk
==
m_ptrLastChunk) { ptrChunk
=
m_ptrFirstChunk; }
if
(ptrChunk
->
DataSize
>=
sMemorySize) {
if
(ptrChunk
->
UsedSize
==
0
) { m_ptrCursorChunk
=
ptrChunk;
return
ptrChunk; } } uiChunksToSkip
=
CalculateNeededChunks(ptrChunk
->
UsedSize);
if
(uiChunksToSkip
==
0
) uiChunksToSkip
=
1
; ptrChunk
=
SkipChunks(ptrChunk, uiChunksToSkip); }
else
{ bContinueSearch
=
false
; } }
return
NULL; }
std::size_t CMemoryPool::MaxValue(
const
std::size_t
&
sValueA,
const
std::size_t
&
sValueB)
const
{
if
(sValueA
>
sValueB) {
return
sValueA; }
return
sValueB; }
void
CMemoryPool::SetMemoryChunkValues(SMemoryChunk
*
ptrChunk,
const
std::size_t
&
sMemBlockSize) {
if
((ptrChunk)) { ptrChunk
->
UsedSize
=
sMemBlockSize; }
else
{ assert(
false
&&
"
Error : Invalid NULL-Pointer passed
"
); } }
SMemoryChunk
*
CMemoryPool::SkipChunks(SMemoryChunk
*
ptrStartChunk, unsigned
int
uiChunksToSkip) { SMemoryChunk
*
ptrCurrentChunk
=
ptrStartChunk;
for
(unsigned
int
i
=
0
; i
<
uiChunksToSkip; i
++
) {
if
(ptrCurrentChunk) { ptrCurrentChunk
=
ptrCurrentChunk
->
Next; }
else
{
assert(
false
&&
"
Error : Chunk == NULL was not expected.
"
);
break
; } }
return
ptrCurrentChunk; }
测试方法:
//
111.cpp : 定义控制台应用程序的入口点。
//
#include
"
stdafx.h
"
#include
"
CMemoryPool.h
"
CMemoryPool
*
g_pMemPool
=
NULL;
class
testMemoryPool {
public
: testMemoryPool(){ }
virtual
~
testMemoryPool(){ }
void
*
operator
new
(std::size_t ObjectSize) {
return
g_pMemPool
->
GetMemory(ObjectSize) ; }
void
operator
delete(
void
*
ptrObject, std::size_t ObjectSize) { g_pMemPool
->
FreeMemory(ptrObject, ObjectSize) ; }
public
:
char
a[
512
];
bool
b;
long
c; };
//
sizeof(32);
int
_tmain(
int
argc, _TCHAR
*
argv[]) {
g_pMemPool
=
new
CMemoryPool();
testMemoryPool
*
test
=
new
testMemoryPool();
if
(test){ delete test; test
=
NULL; }
if
(g_pMemPool) delete g_pMemPool ;
return
0
; }
|
|
原文地址 http://www.cppblog.com/d3d/archive/2008/11/28/68097.aspx |
转载于:https://www.cnblogs.com/lancidie/archive/2010/12/04/1896427.html