ThreadLocal class UML
ThreadLocal 的源代码
// Use of this source code is governed by a BSD-style license // that can be found in the License file. // // Author: Shuo Chen (chenshuo at chenshuo dot com) #ifndef MUDUO_BASE_THREADLOCAL_H #define MUDUO_BASE_THREADLOCAL_H #include <boost/noncopyable.hpp> #include <pthread.h> namespace muduo { template<typename T> class ThreadLocal : boost::noncopyable { public: //构造函数,创建pkey ThreadLocal() { /* 创建的键存放在pkey指定的内存单元,这个键可以被进程中的所有线程使用,但每个线程 把这个键与不同的线程 “私有数据地址” 进行关联。创建新键时,每个线程的数据地址设为NULL值。 ThreadLocal::destructor键的虚构函数 **/ pthread_key_create(&pkey_, &ThreadLocal::destructor); } ~ThreadLocal() { pthread_key_delete(pkey_); } // 获取数据,如果数据还没有,则新建一个 T& value() { T* perThreadValue = static_cast<T*>(pthread_getspecific(pkey_)); if (!perThreadValue) { T* newObj = new T(); //pthread_setspecific使pkey 和 私有数据进行关联 pthread_setspecific(pkey_, newObj); perThreadValue = newObj; } return *perThreadValue; } private: static void destructor(void *x) { T* obj = static_cast<T*>(x); //判断是否为全类型,如果是则delete obj, typedef char T_must_be_complete_type[sizeof(T) == 0 ? -1 : 1]; delete obj; } private: pthread_key_t pkey_; }; } #endif
ThreadLocal 的测试程序
#include <muduo/base/ThreadLocal.h> #include <muduo/base/CurrentThread.h> #include <muduo/base/Thread.h> #include <boost/noncopyable.hpp> #include <stdio.h> class Test:boost::noncopyable { private : std::string name_; public : Test(){ printf("tid=%d,constructing %p\n",muduo::CurrentThread::tid(),this); } ~Test(){ printf("tid= %d,destructing %p %s\n",muduo::CurrentThread::tid(),this,name_.c_str()); } const std::string &name()const{ return name_ ;} void setName(const std::string &n ){ name_ = n ;} }; muduo::ThreadLocal<Test> testObj1; muduo::ThreadLocal<Test> testObj2; void print(){ printf("tid =%d\tobj1 %p\tname=%s\n",muduo::CurrentThread::tid(), &testObj1.value(), testObj1.value().name().c_str()); printf("tid=%d\tobj2 %p name=%s\n", muduo::CurrentThread::tid(), &testObj2.value(), testObj2.value().name().c_str()); } void threadFunc(){ print(); testObj1.value().setName("changed 1") ; testObj2.value().setName("changed 2"); print(); } int main (void ){ testObj1.value().setName("main One"); print(); muduo::Thread t1 (threadFunc) ; t1.start(); t1.join(); testObj2.value().setName("main two" ) ; print(); pthread_exit(0); return 0 ; }
程序输出:
[root@localhost bin]# ./threadlocal_test tid=2915,constructing 0x9435028 tid =2915 obj1 0x9435028 name=main One tid=2915,constructing 0x9435038 tid=2915 obj2 0x9435038 name= tid=2916,constructing 0xb6c00468 tid =2916 obj1 0xb6c00468 name= tid=2916,constructing 0xb6c00478 tid=2916 obj2 0xb6c00478 name= tid =2916 obj1 0xb6c00468 name=changed 1 tid=2916 obj2 0xb6c00478 name=changed 2 tid= 2916,destructing 0xb6c00468 changed 1 tid= 2916,destructing 0xb6c00478 changed 2 tid =2915 obj1 0x9435028 name=main One tid=2915 obj2 0x9435038 name=main two tid= 2915,destructing 0x9435028 main One tid= 2915,destructing 0x9435038 main two [root@localhost bin]# ls