アセンブラを使わないallocaの独自実装 (win32用) part2

id:y-hamigaki氏のご指摘から少し改良してみた・・・が未だにmapの直列化の概念が良く分かっていない・・・
こうなったら最終兵器、なんでもかんでもsynchronizedテクニック*1しかないのだが・・・
脈絡は無いが・・・どーっちだ(笑)とちょっと遊び心を・・・
続きを読む

/**
@note
各関数の最初にsynchronizedをすればとても安全だと思います。
(まだスレッド関連のプログラミングに慣れていません。
*/

#include <windows.h>
#include <list>
#include <map>



typedef std::list<void *> LIST_T;
typedef std::map<DWORD,LIST_T> MAP_T;



static MAP_T gMap;

static void list_free(LIST_T &x){
if(x.size()==0)return;
LIST_T::iterator it = x.begin();
for(;it != x.end();it++){
free(*it);
}
x.clear();
}

void *dkc_alloca(size_t size){
void *pt = malloc(size);
if(NULL==pt) return NULL;

DWORD id = GetCurrentThreadId();
MAP_T::iterator it = gMap.find(id);
if(it == gMap.end())
{
LIST_T gl;
gl.push_back(pt);
gMap.insert(MAP_T::value_type(id,gl));
}else{
(*it).second.push_back(pt);
}
return pt;

}

int dkc_alloca_free()
{
DWORD id = GetCurrentThreadId();
MAP_T::iterator it = gMap.find(id);
if(it == gMap.end())
{
return -1;
}
//以下 synchronizedするととても安全
list_free( (*it).second );

return 0;
}

void dkc_alloca_all_free()
{
//以下 synchronized 省略するが^^;
MAP_T::iterator it = gMap.begin();
for(;it != gMap.end();it++)
{
list_free( (*it).second );
}
gMap.clear();
}


#define TEST_DKC_ALLOCA
#ifdef TEST_DKC_ALLOCA

//dkutil_c使います。
#include <dkutil_c/dkc.h>
int main(){
dkcCheckMemoryLeak(TRUE);
//atexitで登録してあげる
atexit(dkc_alloca_all_free);


const int count = 1;
int i,j;
//後はご自由に
dkc_alloca(12);
for(i=0;i<count;i++){//main loop


char *t = (char *)dkc_alloca(1024);
sprintf(t,"count : %d\n",i);
printf(t);

//32kb shock
dkc_alloca(1024 * 32);

for(j=0;j<1024 * 32;j++)
dkc_alloca(1);//ちまちま確保してイジメル。


//32MB shock
if(NULL==dkc_alloca(1024 * 1024 * 32)){
printf("32MB alloca NULL orz\n");
}
//メインループの最後にこうしておけばリークしないはず・・・。
dkc_alloca_free();

}

//メモリリークしないなり^^

}

#endif

*1:いわいるライブラリの関数すべてにgoogle:Single threaded executionを適用する荒業