基本类型(如(unsigned) int,long, char,指针,c类型的结构体等 )可以采用用 __thread修饰符来定义线程局部变量.
示例如下:
__thread int i; extern __thread struct state s; static __thread char *p;
1
|
__thread std::string * p_thread_name;
|
使用 __thread修饰符来定义一些类的线程局部变量,往往容易造成内存泄漏.
网上实现的Tls类,可以方便用户使用!
头文件:
//Tls.h #ifndef __SAP_UTIL_TLS_H_ #define __SAP_UTIL_TLS_H_ #include <pthread.h> class Tls { public: static int pthread_atexit_add(void *arg, void (*free_fn)(void *) ); static int pthread_atexit_remove(void *arg, void (*free_fn)(void*) ); protected: static void pthread_atexit_done(void *arg); static void pthread_atexit_init(void); protected: static pthread_key_t _pthread_atexit_key; static pthread_once_t _pthread_atexit_control_once; }; #endif实现文件:
// Tls.cpp #include <sys/syscall.h> #include <list> #include "Tls.h" using namespace std; #define gettid() syscall(__NR_gettid) #define TLS_OUT_OF_INDEXES 0xffffffff typedef struct pthread_atexit { void (*free_fn)(void *); void *arg; }pthread_atexit_t; typedef std::list<pthread_atexit_t *> TlsList; pthread_key_t Tls::_pthread_atexit_key = TLS_OUT_OF_INDEXES; pthread_once_t Tls::_pthread_atexit_control_once = PTHREAD_ONCE_INIT; void Tls::pthread_atexit_done(void *arg) { TlsList *id_list = (TlsList*) arg; pthread_atexit_t *id_ptr=NULL; printf("invoke Tls::pthread_atexit_done(): tid=%ld\n",gettid()); for(TlsList::iterator iter=id_list->begin(); iter !=id_list->end(); ++iter) { id_ptr = *iter; if (id_ptr == NULL) continue; if (id_ptr->free_fn) id_ptr->free_fn(id_ptr->arg); delete id_ptr; } delete id_list; } void Tls::pthread_atexit_init(void) { pthread_key_create(&_pthread_atexit_key, pthread_atexit_done); } int Tls::pthread_atexit_add(void *arg, void (*free_fn)(void *)) { const char *myname = "pthread_atexit_add"; pthread_atexit_t *id; TlsList *id_list; if (arg == NULL) { return 0; } pthread_once(&_pthread_atexit_control_once, pthread_atexit_init); if (_pthread_atexit_key == (pthread_key_t) TLS_OUT_OF_INDEXES) { printf("%s(%d): _pthread_atexit_key(%d) invalid\n", myname, __LINE__, _pthread_atexit_key); return (-1); } id = new pthread_atexit_t; if (id == NULL) { printf("%s(%d): new pthread_atexit_t error\n", myname, __LINE__); return -1; } id->free_fn = free_fn; id->arg = arg; id_list = (TlsList*) pthread_getspecific(_pthread_atexit_key); if (id_list == NULL) { id_list = new TlsList(); if (pthread_setspecific(_pthread_atexit_key, id_list) != 0) { printf("%s(%d): pthread_setspecific error, key(%d)\n", myname, __LINE__, _pthread_atexit_key); return -1; } } id_list->push_back(id); return 0; } int Tls::pthread_atexit_remove(void *arg, void (*free_fn)(void*)) { const char *myname = "pthread_atexit_remove"; TlsList *id_list; if (arg == NULL) { return (-1); } if (_pthread_atexit_key == (pthread_key_t) TLS_OUT_OF_INDEXES) { printf("%s(%d): _pthread_atexit_key(%d) invalid\n",myname, __LINE__, _pthread_atexit_key); return (-1); } id_list = (TlsList*) pthread_getspecific(_pthread_atexit_key); if (id_list == NULL) { printf("%s(%d): _pthread_atexit_key(%d) no exist in tid(%lu)\n", myname, __LINE__, _pthread_atexit_key,(unsigned long) pthread_self()); return (-1); } pthread_atexit_t *id_ptr =NULL; TlsList::iterator iter=id_list->begin(); for(; iter !=id_list->end(); ++iter) { id_ptr = *iter; if (id_ptr == NULL) continue; if (id_ptr->free_fn == free_fn && id_ptr->arg == arg) { break; } } if(id_ptr != NULL) { id_list->erase(iter); delete id_ptr; } return (0); }
更多参考:点击打开链接