以下 代码 vs2012 下多线程 海量数据 测试过 无内存泄漏
// TrieTreeTest.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "trie.h"
#include <windows.h>
#include <ctime>
#include "vld.h"
#include "ieee_addr.h"
#define MULTY_THREADS 1
int g_keep_run = 1;
TrieRoot root = {0};
char * create_a_ieee()
{
#if 1
char * text = NULL;
text = (char *)malloc (17);
for(int i = 0; i < 16;i++)
{
int index = rand() % 16;
_snprintf(text + i,1,"%x",index);
}
text[16] = 0;
if(strlen(text)!= 16)
{
printf("fuck error\n");
}
return text;
#else
int index = rand() % (sizeof(text) / sizeof(char *));
return text[index];
#endif
}
char * create_a_string(char * ieee)
{
char * text;
text = (char *)malloc(21);
strcpy(text,ieee);
text[16] = 0;
return text;
}
void printf_handler(void * data)
{
printf("%s\n",data);
}
void free_handler(void * data)
{
free(data);
}
DWORD WINAPI add(LPVOID pM)
{
char * ieee;
char * str;
while(g_keep_run)
{
int time_s = rand() % 2;
ieee = create_a_ieee();
str = create_a_string(ieee);
if(TRIE_SUCCESS == trie_insert(&root,ieee,str))
{
//printf("add [%s]\n",key[index]);
}
else
{
free(str);
}
free(ieee);
Sleep(time_s);
}
return 0;
}
DWORD WINAPI upd(LPVOID pM)
{
char * ieee;
char * str;
char * old_str;
while(g_keep_run)
{
int time_s = rand() % 2;
ieee = create_a_ieee();
str = create_a_string(ieee);
if(TRIE_SUCCESS == trie_update(&root,ieee,str,(void **)&old_str))
{
free(old_str);
}
else
{
free(str);
}
free(ieee);
Sleep(time_s);
}
return 0;
}
DWORD WINAPI sch(LPVOID pM)
{
char * ieee;
while(g_keep_run)
{
int time_s = rand() % 100;
ieee = create_a_ieee();
char * data = NULL;
trie_search(&root,ieee,(void **)&data);
free(ieee);
Sleep(time_s);
}
return 0;
}
DWORD WINAPI del(LPVOID pM)
{
char * ieee;
char * data_pointer;
while(g_keep_run)
{
int time_s = rand() % 100;
ieee = create_a_ieee();
if(TRIE_SUCCESS == trie_delete(&root,ieee,(void **)&data_pointer))
{
free(data_pointer);
}
//else
//printf("del [%s] failed\n",key[index]);
free(ieee);
Sleep(time_s);
}
return 0;
}
DWORD WINAPI fore(LPVOID pM)
{
while(g_keep_run)
{
srand( (unsigned)time(NULL ) );//srand()函数产生一个以当前时间开始的随机种子.应该放在for等循环语句前面 不然要很长时间等待
int index = rand() % 8;
trie_foreach(&root,printf_handler);
Sleep(index);
}
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
int cha;
int count = 20;
void * data_pointer;
srand( (unsigned)time(NULL ) );
trie_init(&root);
#if 1
HANDLE add_handle = CreateThread(NULL, 0, add, NULL, 0, NULL);
HANDLE sch_handle = CreateThread(NULL, 0, sch, NULL, 0, NULL);
HANDLE upd_handle = CreateThread(NULL, 0, upd, NULL, 0, NULL);
HANDLE del_handle = CreateThread(NULL, 0, del, NULL, 0, NULL);
// HANDLE for_handle = CreateThread(NULL, 0, fore, NULL, 0, NULL);
cha = getchar();
g_keep_run = 0;
WaitForSingleObject(add_handle, INFINITE);
WaitForSingleObject(sch_handle, INFINITE);
WaitForSingleObject(upd_handle, INFINITE);
WaitForSingleObject(del_handle, INFINITE);
// WaitForSingleObject(for_handle, INFINITE);
CloseHandle(add_handle);
CloseHandle(sch_handle);
CloseHandle(upd_handle);
CloseHandle(del_handle);
// CloseHandle(for_handle);
// for(int i =0;i<key_size;i++)
// trie_delete(&root,key[i],(void **)&data_pointer);
trie_foreach(&root,free_handler);
trie_destroy(&root);
// getchar();
#else
char * str1 = (char *) malloc(21);
char * str2 = (char *) malloc(21);
char * strout;
sprintf(str1,"fuckyou");
sprintf(str2,"fuckme");
trie_insert(&root,"123456789",str1);
trie_insert(&root,"123123123",str1);
trie_insert(&root,"123123123",str1);
trie_insert(&root,"123123123",str1);
trie_insert(&root,"123123123",str1);
trie_search(&root,"123456789",(void **)&strout);
//trie_update(&root,"123456789",(void *)str2,(void **)&strout);
//free(strout);
if(TRIE_SUCCESS == trie_delete(&root,"123123123",(void **)&strout))
{
//free(strout);
}
if(TRIE_SUCCESS == trie_delete(&root,"123123123",(void **)&strout))
{
//free(strout);
}
free(str1);
free(str2);
trie_destroy(&root);
#endif
return 0;
}
<pre class="cpp" name="code">// *****************************************************************************
// * trie.h
// *
// * an implementation of a trie tree
// *
// * author: zison sun
// *
// * date: 2016-8-16
// *****************************************************************************
#ifndef _MACRO_trie_DATA_STRUCTURE_HEADER_
#define _MACRO_trie_DATA_STRUCTURE_HEADER_
#define WINDOWS 1
#if WINDOWS
#include <windows.h>
#else
#include <pthread.h>
#endif
#define TRIE_SON_NUM 16 //(0-F)
enum trieStatus
{
TRIE_ERROR = 0,
TRIE_SUCCESS = 1,
};
typedef struct tagTrie
{
int href; //引用计数
void * data_pointer; //数据指针
void * addr_in_parent; //自身在父节点中的地址
struct tagTrie * branch[TRIE_SON_NUM];
} Trie, * PTrie;
typedef struct tagTrieRoot
{
#if WINDOWS
HANDLE hMutex;
#else
pthread_rwlock_t trie_lock;
#endif
Trie * proot;
} TrieRoot, * PTrieRoot;
typedef void (*trieCallback)(void *);
trieStatus trie_init(PTrieRoot ptrie_root);
trieStatus trie_insert(PTrieRoot ptrie_root,char * word,void * data_pointer);
trieStatus trie_update(PTrieRoot ptrie_root,char * word,void * data_pointer,void ** old_data_pointer);
trieStatus trie_search(PTrieRoot ptrie_root,char * word,void ** data_pointer);
trieStatus trie_delete(PTrieRoot ptrie_root,char * word,void ** data_pointer);
trieStatus trie_foreach(PTrieRoot ptrie_root,trieCallback call);
trieStatus trie_destroy(PTrieRoot ptrie_root);
#endif //_MACRO_trie_DATA_STRUCTURE_HEADER_
// *****************************************************************************
// * trie.c
// *
// * an implementation of a trie tree
// *
// * author: zison sun
// *
// * date: 2016-8-16
// *****************************************************************************
#include "stdafx.h"
#include "vld.h"
#include <stdlib.h>
#include <string.h>
#include "trie.h"
void _trie_rwlock_rdlock(PTrieRoot ptrie_root);
void _trie_rwlock_wrlock(PTrieRoot ptrie_root);
void _trie_rwlock_unlock(PTrieRoot ptrie_root);
trieStatus _trie_delete(PTrie * pptrie,char * word,void ** data_pointer);
void _trie_foreach(PTrie ptrie,trieCallback call);
void _trie_destroy(PTrie * pptrie);
void _trie_rwlock_rdlock(PTrieRoot ptrie_root)
{
#if WINDOWS
DWORD dReturn = WaitForSingleObject(ptrie_root->hMutex,INFINITE);
#else
#endif
}
void _trie_rwlock_wrlock(PTrieRoot ptrie_root)
{
#if WINDOWS
DWORD dReturn = WaitForSingleObject(ptrie_root->hMutex,INFINITE);
#else
#endif
}
void _trie_rwlock_unlock(PTrieRoot ptrie_root)
{
#if WINDOWS
ReleaseMutex(ptrie_root->hMutex);
#else
#endif
}
int trie_char_to_index(char charsert)
{
if(charsert >= '0' && charsert <= '9' )
return (charsert - '0');
else if(charsert >= 'A' && charsert <= 'F' )
return (charsert - 'A' + 10);
else if(charsert >= 'a' && charsert <= 'f' )
return (charsert - 'a' + 10);
else
return -1;
}
trieStatus trie_word_check(char * word)
{
while(*word)
{
if(-1 == trie_char_to_index(*word))
return TRIE_ERROR;
word++;
}
return TRIE_SUCCESS;
}
PTrie trie_malloc()
{
PTrie ptrie_temp;
ptrie_temp = (PTrie) malloc(sizeof(Trie));
if(!ptrie_temp)
{
return 0;
}
memset(ptrie_temp,0,sizeof(Trie));
return ptrie_temp;
}
void trie_free(PTrie ptrie)
{
if(!ptrie)
return;
//设置父节点中自己的那个索引为NULL
if(ptrie->addr_in_parent)
*((int *)ptrie->addr_in_parent) = NULL;
free(ptrie);
return ;
}
trieStatus trie_init(PTrieRoot ptrie_root)
{
#if WINDOWS
ptrie_root->hMutex = CreateMutex(NULL,FALSE,NULL);
#else
#endif
return TRIE_SUCCESS;
}
/*
* warning: chareset in word should in [0-9][a-f]
*/
trieStatus trie_insert(PTrieRoot ptrie_root,char * word,void * data_pointer)
{
int index = -1;
PTrie ptrie_cur;
PTrie ptrie_new;
trieStatus ret = TRIE_ERROR;
void * data_p;
if(TRIE_ERROR == trie_word_check(word))
return TRIE_ERROR;
if(!ptrie_root)
return TRIE_ERROR;
if(TRIE_SUCCESS == trie_search(ptrie_root,word,&data_p))
return TRIE_ERROR;
_trie_rwlock_wrlock(ptrie_root);
#if 1//debug
char sss_copy[256];
strncpy_s(sss_copy,word,255);
#endif
printf("add [%s] begin text=[%s]\n",word,data_pointer);
if(! ptrie_root->proot)
{
ptrie_root->proot = trie_malloc();
}
ptrie_cur = ptrie_root->proot;
while(*word)
{
index = trie_char_to_index(*word);
if(-1 == index)
goto OnReturn;
ptrie_cur->href++;
if(ptrie_cur->branch[index] == NULL)
{
ptrie_new = trie_malloc();
ptrie_cur->branch[index] = ptrie_new;
ptrie_new->addr_in_parent = &ptrie_cur->branch[index];
}
ptrie_cur = ptrie_cur->branch[index];
word++;
}
ptrie_cur->data_pointer = data_pointer;
ret = TRIE_SUCCESS;
OnReturn:
printf("add [%s] end\n",sss_copy);
_trie_rwlock_unlock(ptrie_root);
return ret;
}
trieStatus trie_if_exist(PTrieRoot prtie_root,char * word)
{
void * data_addr;
return trie_search(prtie_root,word,&data_addr);
}
trieStatus trie_update(PTrieRoot ptrie_root,char * word,void * data_pointer,void ** old_data_pointer)
{
int index = -1;
PTrie ptrie_temp;
trieStatus ret = TRIE_ERROR;
if(TRIE_ERROR == trie_word_check(word))
return TRIE_ERROR;
if(!ptrie_root)
return TRIE_ERROR;
_trie_rwlock_wrlock(ptrie_root);
#if 1//debug
char sss_copy[256];
strncpy_s(sss_copy,word,255);
#endif
if(!ptrie_root->proot)
{
_trie_rwlock_unlock(ptrie_root);
return TRIE_ERROR;
}
printf("update [%s] begin text = [%s]\n",word,data_pointer);
ptrie_temp = ptrie_root->proot;
while(*word)
{
index = trie_char_to_index(*word);
if(-1 == index)
goto OnReturn;
if(ptrie_temp->branch[index] == NULL)
{
goto OnReturn;
}
word++;
ptrie_temp = ptrie_temp->branch[index];
}
*old_data_pointer = ptrie_temp->data_pointer;
ptrie_temp->data_pointer = data_pointer;
ret = TRIE_SUCCESS;
OnReturn:
printf("update [%s] end\n",sss_copy);
_trie_rwlock_unlock(ptrie_root);
return ret;
}
trieStatus trie_search(PTrieRoot ptrie_root,char * word,void ** data_pointer)
{
int index = -1;
PTrie ptrie_temp;
trieStatus ret = TRIE_ERROR;
if(TRIE_ERROR == trie_word_check(word))
return TRIE_ERROR;
if(!ptrie_root)
return TRIE_ERROR;
_trie_rwlock_rdlock(ptrie_root);
#if 1//debug
char sss_copy[256];
strncpy_s(sss_copy,word,255);
#endif
if(!ptrie_root->proot)
{
_trie_rwlock_unlock(ptrie_root);
return TRIE_ERROR;
}
printf("search [%s] begin\n",word);
ptrie_temp = ptrie_root->proot;
while(*word)
{
index = trie_char_to_index(*word);
if(-1 == index)
goto OnReturn;
if(ptrie_temp->branch[index] == NULL)
{
goto OnReturn;
}
word++;
ptrie_temp = ptrie_temp->branch[index];
}
*data_pointer = ptrie_temp->data_pointer ;
ret = TRIE_SUCCESS;
OnReturn:
printf("search [%s] end\n",sss_copy);
_trie_rwlock_unlock(ptrie_root);
return ret;
}
trieStatus trie_delete(PTrieRoot ptrie_root,char * word,void ** data_pointer)
{
#if 1
int index = -1;
PTrie ptrie_cur;
PTrie ptrie_cpy;
int broot = 1;
trieStatus ret = TRIE_ERROR;
*data_pointer = NULL;
if(!ptrie_root)
return TRIE_ERROR;
if(TRIE_ERROR == trie_word_check(word))
return TRIE_ERROR;
if(TRIE_ERROR == trie_search(ptrie_root,word,data_pointer))
return TRIE_ERROR;
_trie_rwlock_wrlock(ptrie_root);
#if 1//debug
char sss_copy[256];
strncpy_s(sss_copy,word,255);
#endif
printf("del [%s] begin\n",word);
if(! ptrie_root->proot)
goto onReturn;
ptrie_cur = ptrie_root->proot;
while(ptrie_cur && *word)
{
index = trie_char_to_index(*word);
if(-1 == index)
goto onReturn;
if(ptrie_cur->branch[index] == NULL)
goto onReturn;
ptrie_cpy = ptrie_cur->branch[index];
if(ptrie_cur->href > 1)
{
ptrie_cur->href--;
broot = 0;
}
else
{
ptrie_cur->href = 0;
if(broot)
{
ptrie_root->proot = NULL;
broot = 0;
}
trie_free(ptrie_cur);
ptrie_cpy->addr_in_parent = NULL;
}
ptrie_cur = ptrie_cpy;
word++;
}
*data_pointer = ptrie_cur->data_pointer ;
printf("%s\n",*data_pointer);
ret = TRIE_SUCCESS;
if(ptrie_cur->href == 0)
trie_free(ptrie_cur);
onReturn:
printf("del [%s] end\n",sss_copy);
_trie_rwlock_unlock(ptrie_root);
return ret;
#else
// 递归
trieStatus ret;
if(!ptrie_root)
return TRIE_ERROR;
if(TRIE_ERROR == trie_word_check(word))
return TRIE_ERROR;
printf("delete begin\n");
_trie_rwlock_wrlock(ptrie_root);
ret = _trie_delete(&ptrie_root->proot,word,data_pointer);
printf("delete end\n");
_trie_rwlock_unlock(ptrie_root);
return ret;
#endif
}
trieStatus _trie_delete(PTrie *pptrie,char * word,void ** data_pointer)
{
int index;
if(!*pptrie)
return TRIE_ERROR;
if(*word)
{
index = trie_char_to_index(*word);
if(-1 == index)
return TRIE_ERROR;
if((*pptrie)->branch[index] == NULL)
{
return TRIE_ERROR;
}
word++;
if(TRIE_SUCCESS == _trie_delete(&(*pptrie)->branch[index],word,data_pointer))
{
(*pptrie)->href--;
if( (*pptrie)->href ==0)
{
trie_free(*pptrie);
*pptrie = NULL;
}
}
}
else
{
if( (*pptrie)->href ==0)
{
*data_pointer = (*pptrie)->data_pointer ;
trie_free(*pptrie);
*pptrie = NULL;
}
}
return TRIE_SUCCESS;
}
trieStatus trie_foreach(PTrieRoot ptrie_root,trieCallback call)
{
if(!ptrie_root)
return TRIE_ERROR;
_trie_rwlock_rdlock(ptrie_root);
printf("foreach begin\n");
_trie_foreach(ptrie_root->proot,call);
printf("foreach end\n");
_trie_rwlock_unlock(ptrie_root);
return TRIE_SUCCESS;
}
void _trie_foreach(PTrie ptrie,trieCallback call)
{
int i = 0;
if(!ptrie)
return;
if(0 == ptrie->href && NULL != ptrie->data_pointer)
{
call(ptrie->data_pointer);
return ;
}
for(i = 0; i < TRIE_SON_NUM;i++)
{
if((ptrie)->branch[i])
{
_trie_foreach(ptrie->branch[i],call);
}
}
return;
}
trieStatus trie_destroy(PTrieRoot ptrie_root)
{
if(!ptrie_root)
return TRIE_ERROR;
_trie_rwlock_wrlock(ptrie_root);
printf("destroy begin\n");
_trie_destroy(&ptrie_root->proot);
ptrie_root->proot = NULL;
printf("destroy end\n");
_trie_rwlock_unlock(ptrie_root);
#if WINDOWS
CloseHandle(ptrie_root->hMutex);
ptrie_root->hMutex = 0;
#else
#endif
return TRIE_SUCCESS;
}
void _trie_destroy(PTrie * pptrie)
{
int i = 0;
if(!*pptrie)
return;
for(i = 0; i < TRIE_SON_NUM;i++)
{
if((*pptrie)->branch[i])
{
_trie_destroy(&(*pptrie)->branch[i]);
trie_free((*pptrie)->branch[i]);
}
}
trie_free(*pptrie);
*pptrie = NULL;
return ;
}