线程局部变量

来源:互联网 发布:傲盾网络加速器免费版 编辑:程序博客网 时间:2024/06/16 13:20


学习java的时候,有个thread_local变量,表示是线程局部的变量。

unix中介绍到了这个的内容:

主要是用到了一个pthread_key_t变量来维护。


以下是一个程序:启动多个线程,每个线程都保存一些k-v内容。k相等,但是v不同。

每个线程的buf的格式如下:

前面4个字节是一个int,表示总共有多少条记录;

紧接着的4个字节是一个int,表示buf有效的总长度(包括头部本身);

然后就是具体的每条记录的内容了。

每个记录的格式又为:

   前面4个字节为该记录总长度,接着4个字节为k的长度,接着是k的内容,接着是v的内容。


#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>


static pthread_key_t key;
static pthread_once_t init_done=PTHREAD_ONCE_INIT;
pthread_mutex_t env_mutex=PTHREAD_MUTEX_INITIALIZER;


extern char** environ;
char* gval[5]={"hello","world","hi","zhuli","good"};
int arg_len=8192;//buf length
int thread_cnt=1;
static void thread_init(void){
pthread_key_create(&key,free);//这个key只初始化一次
}


char * getenv(const char* name){
   int i,len;
   char *envbuf;


   pthread_t tid=pthread_self();
   printf("in thread ,tid=%d\n",tid);


   pthread_once(&init_done,thread_init);//只初始化一次
   pthread_mutex_lock(&env_mutex);


   envbuf=(char*)pthread_getspecific(key);
   if(envbuf==NULL){
envbuf=(char*)malloc(arg_len);
if(envbuf==NULL){
pthread_mutex_unlock(&env_mutex);
return (NULL);
}
pthread_setspecific(key,envbuf);
   }
   len=strlen(name);
   int find=0;
   for(i=0;environ[i]!=NULL;i++){
//        printf("tid:%d,%s\n",tid,environ[i]);
if(strncmp(name,environ[i],len)==0 && environ[i][len]=='='){
strcpy(envbuf,&environ[i][len+1]);
//pthread_mutex_unlock(&env_mutex);
//return (envbuf);
find=1;
}
   }
   pthread_mutex_unlock(&env_mutex);
   if(find==1)
    return envbuf;
   return NULL;


}




//save thread local data
//first 4byte:rec count
//second 4 byte:rec length(include head info)
void putdata(const void* k,void *val){


  const char* pre="\n----------putdata-------";
  char * buf=(char *)pthread_getspecific(key);
  int rec_cnt=0;
  int buf_len=0;
  if(buf==NULL){
        printf("%s empty buf\n",pre);
buf=malloc(arg_len);
        pthread_setspecific(key,buf);
  }else{
     rec_cnt=*((int*)buf);
     buf_len=*((int*)(buf+4));
     printf("%s rec_cnt=%d,rec_len=%d\n",pre,rec_cnt,buf_len);
  }


  char * nk=(char*)k;
  int klen=strlen(k);
  char *nv=(char*)val;
  int vlen=strlen(nv);
  printf("k=%s,v=%s,klen=%d,vlen=%d\n",nk,nv,klen,vlen);
  //char buf[klen+vlen+6];
  
  //total len


  //first 4byte:total len,next 4byte:klen,next key cont,next val cont; 
  int total_len=klen+vlen+4+4;
  printf("total len=%d,0x%xH\n",total_len,total_len);




  //length of record
  int index=buf_len==0?8:buf_len;//start position of this key-value pair
  buf[index++]=total_len;
  buf[index++]=total_len>>8 ;//little endien
  buf[index++]=total_len>>16;
  buf[index++]=total_len>>24;




  printf("buf[0]=0x%xH,buf[1]=0x%xH,buf[2]=0x%xH,buf[3]=0x%xH\n",buf[buf_len+0],buf[buf_len+1],buf[buf_len+2],buf[buf_len+3]);


 
  //length of this key
  buf[index++]=klen;
  buf[index++]=klen>>8;
  buf[index++]=klen>>16;
  buf[index++]=klen>>24;


  int i=0;
  //fill key content  
  for(i=0;i<klen;i++){
     printf("%c",nk[i]);
     buf[index++]=nk[i];
  }
  //fill value content
  for(i=0;i<vlen;i++){
     buf[index++]=nv[i];
  }
  


  //modify whole buf rec_cnt,and length
  rec_cnt++;
  buf_len+=total_len;
  buf[0]=rec_cnt;
  buf[1]=rec_cnt>>8;
  buf[2]=rec_cnt>>16;
  buf[3]=rec_cnt>>24;


  buf[4]=buf_len;
  buf[5]=buf_len>>8;
  buf[6]=buf_len>>16;
  buf[7]=buf_len>>24;


  printf("%s,after save data:rec_cnt:%d,buf_len=%d\n",pre,*((int*)buf),*((int*)(buf+4)));
}

//获取k对应的内容
void * getdata(const char* k){
   char *pre="\n------getdata-----";
   char *buf=pthread_getspecific(key);
   if(buf==NULL){
     printf("%sis empty\n",pre);
     return (NULL);
   }


   int rec_cnt=*((int*)(buf));
   int buf_len=*((int*)(buf+4));
   printf("%s,rec_cnt=%d,buf_len=%d\n",pre,rec_cnt,buf_len);


   //loop
   int rec_offset=8;
   int *p=(int*)(buf+rec_offset);
   int *keylp=(int*)(buf+rec_offset+4);
   int find=0;
   int res=0;
   while(1){


  res=strncmp(k,*((char*)(buf+rec_offset+8)),*keylp);
if(!res){
find=1;

                //未写完
char resbuf[];
}
   }
}



//线程入口函数
void * thread_entry(void * arg){
  
  const char* pre="\n--------thread_entry---------";


  pthread_once(&init_done,thread_init);
  // getenv("SHELL");
  pthread_t tid=pthread_self();
  int *index=(int*)arg;
  printf("%stid=%d,index=%d,val=%s\n",pre,tid,*index,gval[*index]);
  putdata("str",gval[*index]);
  putdata("smile","do it now");
}




void main(){
  
  pthread_t tid[thread_cnt];
  int i=0;
  int idx[thread_cnt];
  for(;i<thread_cnt;i++){
    idx[i]=i;
    pthread_create(&tid[i],NULL,&thread_entry,idx+i);
  }
  
  sleep(5);  
}

0 0
原创粉丝点击