功能:
1.C實現的簡單的,可擴展的內存chunk管理器;
2.支持Top, Push, Pop幾種簡單的操作;
3.由於一個內存chunk可以有多個元素,不同的chunk可以大小不等;
優點:
1.可以將其擴展爲一個簡單的內存管理器,實現分配和釋放的cache機制;
2.可以將其作爲雙向隊列的內部的容器類;
3.用這個chunk存儲大量的簡單對象(支持FIFO)效率遠比用雙向鏈表高(速度),同時更節約內存(雙向鏈表一個node,需要兩個指針維護);
代碼如下,compile and test in visual studio 2005:
#ifndef _CHUNK_LIST_H_
#define _CHUNK_LIST_H_
#define INIT_ELEM_COUNT 20
typedef struct tagChunk
{
size_t cur;
size_t end;
tagChunk* next;
tagChunk* prev;
char buf[0];
}Chunk, *pChunk;
void InitChunk( pChunk* newChk, size_t elemSize, size_t elemCount )
{
pChunk chk = *newChk;
chk = (pChunk)malloc(elemCount * elemSize + sizeof(Chunk));
if( chk )
{
chk->cur = 0;
chk->end = elemSize * elemCount;
chk->next = 0;
chk->prev = 0;
*newChk = chk;
}
}
void* Push( pChunk* chk, size_t elemSize )
{
pChunk curChk = *chk;
if( curChk->cur + elemSize > curChk->end )
{
InitChunk( &curChk->next, elemSize, INIT_ELEM_COUNT);
*chk = curChk->next;
if( curChk )
{
(*chk)->prev = curChk;
}
curChk = *chk;
}
size_t loc = curChk->cur;
curChk->cur += elemSize;
return curChk->buf + loc;
}
void Pop( pChunk* chk, size_t elemSize )
{
pChunk curChk = *chk;
if( ( curChk->cur - elemSize ) < 0 )
{
if( curChk->prev )
{
*chk = curChk->prev;
free( curChk );
curChk = *chk;
}
else
{
return;
}
}
curChk->cur -= elemSize;
}
void* Top( pChunk* chk, size_t elemSize )
{
pChunk curChk = *chk;
if( (int)( curChk->cur - elemSize ) < 0 )
{
if( curChk->prev )
{
*chk = curChk->prev;
curChk = *chk;
}
else
{
return NULL;
}
}
return curChk->buf + curChk->cur - elemSize;
}
void UnInit( pChunk chk )
{
if( chk )
{
pChunk head = chk->prev;
pChunk tail = chk->next;
while( head )
{
pChunk prev = head->prev;
free( head );
head = prev;
}
while( tail )
{
pChunk next = tail->next;
free( tail );
tail = next;
}
free( chk );
}
}
pChunk GetHead( pChunk chk )
{
if( !chk )
return 0;
pChunk cur = chk;
while( cur->prev )
{
cur = cur->prev;
}
return cur;
}
pChunk GetTail( pChunk chk )
{
if( !chk )
return 0;
pChunk cur = chk;
while( cur->next )
{
cur = cur->next;
}
return cur;
}
size_t GetChunkCount( pChunk chk )
{
if( !chk )
return 0;
pChunk head = GetHead( chk );
size_t count = 0;
while( head )
{
count++;
head = head->next;
}
return count;
}
void TestChunk()
{
const int itemLen = 400;
int item[itemLen];
for( int i = 0; i < itemLen; i++ )
item[i] = i;
pChunk chk = 0;
InitChunk( &chk, sizeof(int), INIT_ELEM_COUNT );
for( int i = 0; i < itemLen; i++ )
{
*(int*)Push( &chk, sizeof(int) ) = item[i];
}
for( int i = 0; i < itemLen; i++ )
{
assert( *(int*)Top( &chk, sizeof(int) ) == item[itemLen - 1 - i]);
Pop( &chk, sizeof(int) );
}
( GetChunkCount( chk ) == itemLen / INIT_ELEM_COUNT );
UnInit( chk );
}
#endif