アセンブラを使わない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を適用する荒業