精品主页 | 软件下载 | 系统下载 | 精品导航| 精彩图片 | 转帖工具 | 版主申请 | 影视下载

查看完整版本: 为C 标准库容器写自己的内存分配程序

mxh1998 2008-3-26 22:54

为C 标准库容器写自己的内存分配程序

  


                    根据sgi 的STL源码的二级分配算法改写的内存池分配程序,只要稍微修改就可以实现共享内存方式管理,使用C  标准库容器中的map,set,multimap,multiset测试通过,vector测试通不过,原因是在内存回收的时候考虑的比较简单,vector每次分配内存个数不固定,回收也不固定,这样的话,程序还需要继续完善。


  内存池管理程序源码如下:<?xml:namespace prefix = std /><std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><std::size_t><?xml:namespace prefix = sizeof(Cookie)<<std /><sizeof(Cookie)<<std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><std::endl;< p><MAP>











以下是引用片段:

#ifndefMY_ALLOCATOR_H_

#defineMY_ALLOCATOR_H_

#include"stdafx.h[/img]#include&lt;limits&gt;

#include&lt;iostream&gt;

namespacehappyever

{

enum{NODENUMS=2};

union_Obj

{

union_Obj*M_free_list_link;

charM_client_data[1];

};

typedefunion_ObjObj;

struct_Cookie

{

intiShmKey;/*共享内存键值*/

intiShmID;/*iShmKey对应的shmid*/

intiSemKey;/*锁信号键值*/

intiSemID;/*锁信号标识*/

intiTotalsize;/*容器总容量*/

void*pStartall;/*共享内存自身地址*/

char*pStartfree;/*自由空间的开始地址*/

char*pEndfree;/*自由空间的结束地址*/

intiUseNum[NODENUMS];

/*用来存放free_list中节点的size*/

shortsFreelistIndex[NODENUMS];

/*存放分配内存节点的链表*/

Obj*uFreelist[NODENUMS];

};

typedefstruct_CookieCookie;

//Obj;

//Cookie;

staticCookie*pHead=NULL;

template&lt;classT&gt;

classMyAlloc

{

private:

staticconstintALIGN=sizeof(Obj);

intround_up(intbytes);

intfreelist_index(intbytes);

intfreelist_getindex(intbytes);

char*chunk_alloc(intsize,int*nobjs);

void*refill(intnum,intn);

public:

//typedefinitions

typedefTvalue_type;

typedefT*pointer;

typedefconstT*const_pointer;

typedefT&amp;reference;

typedefconstT&amp;const_reference;

typedefstd::size_tsize_type;

typedefstd::ptrdiff_tdifference_type;

template&lt;classU&gt;

structrebind

{

typedefMyAlloc&lt;U&gt;other;

};

pointeraddress(referencevalue)const

{

return&amp;value;

}

const_pointeraddress(const_referencevalue)const

{

return&amp;value;

}

MyAlloc()throw()

{

std::cout&lt;&lt;"MyAlloc"&lt;&lt;std::endl;

}

MyAlloc(constMyAlloc&amp;x)throw()

{

std::cout&lt;&lt;"constMyAlloc"&lt;&lt;std::endl;

}

template&lt;classU&gt;

MyAlloc(constMyAlloc&lt;U&gt;&amp;x)throw()

{

std::cout&lt;&lt;"constMyAlloc&lt;U&gt;"&lt;&lt;std::endl;

}

~MyAlloc()throw()

{

std::cout&lt;&lt;"~MyAlloc"&lt;&lt;std::endl;

}

size_typemax_size()constthrow()

{

returnstd::numeric_limits&lt;std::size_t&gt;::max()/sizeof(T);

}

//voidPrintFreelistAndCookie();

pointerallocate(size_typenum,constvoid*=0)

{

pointerret=0;

Obj**my_free_list;

Obj*result;

intindex;

//printmessageandallocatememorywithglobalnew

std::cerr&lt;&lt;"allocate"&lt;&lt;num&lt;&lt;"element(s)[/img]&lt;&lt;"ofsize"&lt;&lt;sizeof(T)&lt;&lt;std::endl;

index=freelist_index(sizeof(T));

if(index&gt;=NODENUMS)

{

returnNULL;

}

my_free_list=pHead-&gt;uFreelist index;

//Lock(semid,LOCK_NUM);

result=*my_free_list;

if(result==0)

{

ret=(pointer)refill((int)num,round_up(sizeof(T)));

}

else

{

*my_free_list=result-&gt;M_free_list_link;

ret=(pointer)result;

}

//UnLock(semid,LOCK_NUM);

pHead-&gt;iUseNum[index]=pHead-&gt;iUseNum[index] (int)num;

if(0==ret)

{

std::cerr&lt;&lt;"allocmemoryfail!"&lt;&lt;std::endl;

exit(1);

}

std::cerr&lt;&lt;"allocatedat:"&lt;&lt;(void*)ret&lt;&lt;std::endl;

PrintFreelistAndCookie();

returnret;

}

voidconstruct(pointerp,constT&amp;value)

{

//initializememorywithplacementnew

new((void*)p)T(value);

}

voiddestroy(pointerp)

{

//destroyobjectsbycallingtheirdestructor

p-&gt;~T();

}

voiddeallocate(pointerp,size_typenum)

{

Obj**my_free_list;

Obj*q;

intindex;

index=freelist_getindex(sizeof(T));

if(index&gt;=NODENUMS)

{

std::cerr&lt;&lt;"deallocatememoryfail!"&lt;&lt;std::endl;

exit(1);

}

my_free_list=pHead-&gt;uFreelist index;

q=(Obj*)p;

//Lock(semid,LOCK_NUM);

/*这个地方可能会有问题*/

//for(inti=0;i&lt;(int)num;i  )

{

q-&gt;M_free_list_link=*my_free_list;

*my_free_list=q;

}

//UnLock(semid,LOCK_NUM);

pHead-&gt;iUseNum[index]=pHead-&gt;iUseNum[index]-(int)num;



std::cerr&lt;&lt;"deallocate"&lt;&lt;num&lt;&lt;"element(s)[/img]&lt;&lt;"ofsize"&lt;&lt;sizeof(T)

&lt;&lt;"at:"&lt;&lt;(void*)p&lt;&lt;std::endl;

PrintFreelistAndCookie();

}

};

template&lt;classT&gt;

intMyAlloc&lt;T&gt;::round_up(intbytes)

{

inti;

i=bytes;

if(bytes&lt;ALIGN)

{

i=ALIGN;

}

std::cout&lt;&lt;"round_up:bytes="&lt;&lt;bytes&lt;&lt;",return="&lt;&lt;i&lt;&lt;std::endl;

returni;

};

template&lt;classT&gt;

intMyAlloc&lt;T&gt;::freelist_index(intbytes)

{

inti;

for(i=0;i&lt;NODENUMS;i  )

{

if(pHead-&gt;sFreelistIndex[i]==bytes)

break;

}

if(i&gt;=NODENUMS)

{

for(i=0;i&lt;NODENUMS;i  )

{

if(pHead-&gt;sFreelistIndex[i]==0)

{

pHead-&gt;sFreelistIndex[i]=bytes;

std::cout&lt;&lt;"freelist_index:bytes="&lt;&lt;bytes&lt;&lt;",return="&lt;&lt;i&lt;&lt;std::endl;

returni;

}

}

}

std::cout&lt;&lt;"freelist_index:bytes="&lt;&lt;bytes&lt;&lt;",return="&lt;&lt;i&lt;&lt;std::endl;

returni;

};

template&lt;classT&gt;

intMyAlloc&lt;T&gt;::freelist_getindex(intbytes)

{

inti;

for(i=0;i&lt;NODENUMS;i  )

{

if(pHead-&gt;sFreelistIndex[i]==bytes)

break;

}

std::cout&lt;&lt;"freelist_getindex:bytes="&lt;&lt;bytes&lt;&lt;",return="&lt;&lt;i&lt;&lt;std::endl;

returni;

};

template&lt;classT&gt;

char*MyAlloc&lt;T&gt;::chunk_alloc(intsize,int*nobjs)

{

char*result;

intcounts=*nobjs;

inttotal_bytes=size*counts;

intbytes_left=int(pHead-&gt;pEndfree-pHead-&gt;pStartfree);

std::cout&lt;&lt;"chunk_alloc:total_bytes="&lt;&lt;total_bytes

&lt;&lt;",bytes_left="&lt;&lt;bytes_left&lt;&lt;std::endl;

if(bytes_left&gt;=total_bytes)

{

result=pHead-&gt;pStartfree;

pHead-&gt;pStartfree =total_bytes;

std::cout&lt;&lt;"chunk_alloc:total_bytes="&lt;&lt;total_bytes

&lt;&lt;",result="&lt;&lt;*result&lt;&lt;",start_free="&lt;&lt;&amp;(pHead-&gt;pStartfree)&lt;&lt;std::endl;

}

elseif(bytes_left&gt;=size)

{

counts=bytes_left/size;

total_bytes=size*counts;

result=pHead-&gt;pStartfree;

pHead-&gt;pStartfree =total_bytes;

*nobjs=counts;

std::cout&lt;&lt;"chunk_alloc:total_bytes="&lt;&lt;total_bytes&lt;&lt;",nobjs="&lt;&lt;nobjs

&lt;&lt;",result="&lt;&lt;*result&lt;&lt;",start_free="&lt;&lt;&amp;(pHead-&gt;pStartfree)&lt;&lt;std::endl;

}

else

{

/*还需要处理回收其他空闲freelist里面的空间*/

result=NULL;

}

return(result);

};

template&lt;classT&gt;

void*MyAlloc&lt;T&gt;::refill(intnum,intn)

{

intcounts=num;

int*nobjs=&amp;counts;

char*chunk;

Obj**my_free_list;

Obj*result;

Obj*current_obj;

Obj*next_obj;

inti;

chunk=chunk_alloc(n,nobjs);

if(chunk==NULL)

{

return(chunk);

}

counts=*nobjs;

if(1==counts)

{

return(chunk);

}

my_free_list=pHead-&gt;uFreelist freelist_index(n);

result=(Obj*)chunk;

*my_free_list=next_obj=(Obj*)(chunk n*num);

for(i=1;;i  )

{

current_obj=next_obj;

next_obj=(Obj*)((char*)next_obj n);

if(counts-1==i)

{

current_obj-&gt;M_free_list_link=0;

break;

}

else

{

current_obj-&gt;M_free_list_link=next_obj;

}

}

return(result);

};

/*这个函数可以改写成自己的共享内存分配函数*/

staticvoidInitShm()

{

inti,size=1000;

pHead=(Cookie*)malloc(sizeof(Cookie) size);

pHead-&gt;iTotalsize=sizeof(Cookie) size;

pHead-&gt;pStartall=pHead;

pHead-&gt;pStartfree=(char*)pHead sizeof(Cookie);

pHead-&gt;pEndfree=(char*)pHead pHead-&gt;iTotalsize;

for(i=0;i&lt;NODENUMS;i  )

{

pHead-&gt;sFreelistIndex[i]=0;

pHead-&gt;uFreelist[i]=0;

pHead-&gt;iUseNum[i]=0;

}

}

staticvoidPrintFreelistAndCookie()

{

inti,j;

Obj*my_free_list;

std::cout&lt;&lt;"Cookieinfo:"&lt;&lt;std::endl;

std::cout&lt;&lt;"sizeof(structCookie)="&lt;&lt;sizeof(Cookie)&lt;&lt;std::endl;

std::cout&lt;&lt;"Totalsize="&lt;&lt;pHead-&gt;iTotalsize&lt;&lt;std::endl;

std::cout&lt;&lt;"UsedSize="&lt;&lt;int(pHead-&gt;pStartfree-(char*)pHead)&lt;&lt;std::endl;

std::cout&lt;&lt;"FreepoolSize="&lt;&lt;int(pHead-&gt;pEndfree-pHead-&gt;pStartfree)&lt;&lt;std::endl;

std::cout&lt;&lt;"Startall="&lt;&lt;&amp;(pHead-&gt;pStartall)&lt;&lt;std::endl;

std::cout&lt;&lt;"Startfree="&lt;&lt;&amp;(pHead-&gt;pStartfree)&lt;&lt;std::endl;

std::cout&lt;&lt;"Endfree="&lt;&lt;&amp;(pHead-&gt;pEndfree)&lt;&lt;std::endl;

std::cout&lt;&lt;"nFreelistinfo:"&lt;&lt;std::endl;

for(i=0;i&lt;NODENUMS;i  )

{

j=0;

std::cout&lt;&lt;"iUseNum["&lt;&lt;i&lt;&lt;"]="&lt;&lt;pHead-&gt;iUseNum[i]&lt;&lt;std::endl;

std::cout&lt;&lt;"FreelistIndex["&lt;&lt;i&lt;&lt;"]="&lt;&lt;pHead-&gt;sFreelistIndex[i]&lt;&lt;std::endl;

my_free_list=pHead-&gt;uFreelist[i];

if(my_free_list-&gt;M_client_data!=0)

{

while(my_free_list-&gt;M_client_data!=0)

{

j  ;

my_free_list=my_free_list-&gt;M_free_list_link;

}

std::cout&lt;&lt;"free_list["&lt;&lt;i&lt;&lt;"];nodecounts="&lt;&lt;j&lt;&lt;std::endl;

}

}

}

template&lt;classT1,classT2&gt;

booloperator==(constMyAlloc&lt;T1&gt;&amp;,constMyAlloc&lt;T2&gt;&amp;)throw()

{

returntrue;

}

template&lt;classT1,classT2&gt;

booloperator!=(constMyAlloc&lt;T1&gt;&amp;,constMyAlloc&lt;T2&gt;&amp;)throw()

{

returnfalse;

}

}

#endif/*MY_ALLOCATOR_H_*/

测试程序的源码如下:



//MyStl.cpp:定义控制台应用程序的入口点。

//

#include"stdafx.h[/img]#include&lt;map&gt;

#include&lt;vector&gt;

#include&lt;string&gt;

#include&lt;utility&gt;

#include&lt;iostream&gt;

#include"MyAlloc.h[/img]usingnamespacestd;

int_tmain(intargc,_TCHAR*argv[])

{

happyever::InitShm();

multimap&lt;string,int,less&lt;string&gt;,happyever::MyAlloc&lt;string&gt;&gt;m;

m.insert(make_pair(string("Harry"),32));

m.insert(make_pair(string("Mary"),59));

m.insert(make_pair(string("Roger"),18));

m.insert(make_pair(string("Nancy"),37));

m.insert(make_pair(string("Mary"),23));



typedefmultimap&lt;string,int,less&lt;string&gt;,happyever::MyAlloc&lt;string&gt;&gt;::iteratorIter;

for(Iterp=m.begin();p!=m.end();p  )

{

cout&lt;&lt;p-&gt;first&lt;&lt;","&lt;&lt;p-&gt;second&lt;&lt;endl;

}

Iterp=m.find("Harry");

m.erase(p);

/*p=m.find("Harry");

cout&lt;&lt;"Harryis:"&lt;&lt;p-&gt;second&lt;&lt;"."&lt;&lt;endl;*/



for(Iterp=m.begin();p!=m.end();p  )

{

cout&lt;&lt;p-&gt;first&lt;&lt;","&lt;&lt;p-&gt;second&lt;&lt;endl;

}



return0;

}

以上程序在vs2005,vc6上测试通过。使用MinGW编译的时候只需要去掉vc的预编译头文件

#include"stdafx.h"


  即可。


  以上程序只要稍微修改,就可以实现共享内存的管理,可以方便的使用标准库提供的容器。加上信号量的锁机制。


  以上为了学习而改写的SGI的stl二级分配算法实现的。以上代码存在一定的局限性。我另外完整实现了共享内存管理的STL标准的alloctor程序,使用posix信号量加锁。目前应用在aix的xlC编译环境下。因为源码涉及公司的商业秘密,所以不能公开。但基本上以上源码已经体现了自己管理内存的完整思路,供这方面需求的朋友一起学习研究用。</MAP></std::endl;<></std::endl;<></std::endl;<></std::endl;<></std::endl;<></std::endl;<></std::endl;<></sizeof(Cookie)<<std::endl;<></std::size_t></std::endl;<></std::endl;<></std::endl;<></std::endl;<>
页: [1]
查看完整版本: 为C 标准库容器写自己的内存分配程序