[Muduo网络库源码分析] (9) base/Thread.cc_h_CurrentThread_h线程对象
2017-07-31 09:25
561 查看
线程对象
实现:实现Thread类、ThreadData结构体 、CurrentThread命名空间
功能:实现线程对象并实现当前线程信息存储
知识点:
__thread__thread是GCC内置的线程局部存储设施,存取效率可以和全局变量相比。__thread变量每一个线程有一份独立实体,各个线程的值互不干扰。可以用来修饰那些带有全局性且值可能变,但是又不值得用全局变量保护的变量。
__thread使用规则:只能修饰POD类型(类似整型指针的标量,不带自定义的构造、拷贝、赋值、析构的类型,二进制内容可以任意复制memset,memcpy,且内容可以复原),不能修饰class类型,因为无法自动调用构造函数和析构函数,可以用于修饰全局变量,函数内的静态变量,不能修饰函数的局部变量或者class的普通成员变量,且__thread变量值只能初始化为编译器常量(值在编译器就可以确定const int i=5,运行期常量是运行初始化后不再改变const int i=rand()).
Pthread_atfork()函数
boost::weak_pt弱指针
prctl函数
用途:
可用于创建线程,创建多线程程序,可用于创建线程池。
模块拆分与封装:
已把其线程对象模块单独分离出来,并利用Makefile统一编译,模块代码地址如下:https://github.com/chudongfang/Learn_From_Muduo/tree/master/Thread
代码及分析:
Thread.cc
// 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) #include <muduo/base/Thread.h> #include <muduo/base/CurrentThread.h> #include <muduo/base/Exception.h> #include <muduo/base/Logging.h> #include <boost/static_assert.hpp> #include <boost/type_traits/is_same.hpp> #include <boost/weak_ptr.hpp> #include <errno.h> #include <stdio.h> #include <unistd.h> #include <sys/prctl.h> #include <sys/syscall.h> #include <sys/types.h> #include <linux/unistd.h> namespace muduo { namespace CurrentThread { //线程id __thread int t_cachedTid = 0; //线程名 __thread char t_tidString[32]; __thread int t_tidStringLength = 6; __thread const char* t_threadName = "unknown"; //判断int和pid_t类型是否相同 const bool sameType = boost::is_same<int, pid_t>::value; //如果类型不相同则断言false,编译出错 ?? BOOST_STATIC_ASSERT(sameType); } namespace detail { //通过系统调用syscall获取当前线程 pid_t gettid() { return static_cast<pid_t>(::syscall(SYS_gettid)); } //更新当前线程信息 void afterFork() { muduo::CurrentThread::t_cachedTid = 0; muduo::CurrentThread::t_threadName = "main"; CurrentThread::tid(); // no need to call pthread_atfork(NULL, NULL, &afterFork); } // 该类用于初始化CurrentThread信息为当先主线程信息,并且在创建子线程时更新CurrentThread信息 class ThreadNameInitializer { public: ThreadNameInitializer() { muduo::CurrentThread::t_threadName = "main"; //获取当前ID信息 CurrentThread::tid(); //子进程执行afterfork //pthread_atfork(fork前函数,父进程执行的函数,子线程执行的函数) pthread_atfork(NULL, NULL, &afterFork); } }; //初始CurrentThread信息 ThreadNameInitializer init; //以ThreadData的数据形式向子线程传参 struct ThreadData { typedef muduo::Thread::ThreadFunc ThreadFunc; ThreadFunc func_; string name_; //智能指针,弱引用,不对引用计数器加一 //用来观察 boost::weak_ptr<pid_t> wkTid_; ThreadData(const ThreadFunc& func, const string& name, const boost::shared_ptr<pid_t>& tid) : func_(func), name_(name), wkTid_(tid) { } void runInThread() { //得到当前线程ID pid_t tid = muduo::CurrentThread::tid(); //获取所管理的对象的强引用指针。 boost::shared_ptr<pid_t> ptid = wkTid_.lock(); //修改主进程类中pid_为当前进程ID if (ptid) { *ptid = tid; ptid.reset(); } muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str(); //设置进程名 ::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName); try { //运行函数 func_(); //运行完成修改CurrentThread中线程名 muduo::CurrentThread::t_threadName = "finished"; } catch (const Exception& ex) { //对于其抛出的异常类,显示erro muduo::CurrentThread::t_threadName = "crashed"; fprintf(stderr, "exception caught in Thread %s\n", name_.c_str()); fprintf(stderr, "reason: %s\n", ex.what()); fprintf(stderr, "stack trace: %s\n", ex.stackTrace()); abort(); } catch (const std::exception& ex) { muduo::CurrentThread::t_threadName = "crashed"; fprintf(stderr, "exception caught in Thread %s\n", name_.c_str()); fprintf(stderr, "reason: %s\n", ex.what()); abort(); } catch (...) { muduo::CurrentThread::t_threadName = "crashed"; fprintf(stderr, "unknown exception caught in Thread %s\n", name_.c_str()); throw; // rethrow } } }; //子线程函数 //开始线程 void* startThread(void* obj) { ThreadData* data = static_cast<ThreadData*>(obj); data->runInThread(); delete data; return NULL; } } } using namespace muduo; //获取当前线程ID,并赋值给变量 void CurrentThread::cacheTid() { if (t_cachedTid == 0) { t_cachedTid = detail::gettid(); t_tidStringLength = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid); } } //判断是否是主线程 bool CurrentThread::isMainThread() { return tid() == ::getpid(); } //调用系统调用实现延时 void CurrentThread::sleepUsec(int64_t usec) { struct timespec ts = { 0, 0 }; ts.tv_sec = static_cast<time_t>(usec / Timestamp::kMicroSecondsPerSecond); ts.tv_nsec = static_cast<long>(usec % Timestamp::kMicroSecondsPerSecond * 1000); ::nanosleep(&ts, NULL); } AtomicInt32 Thread::numCreated_; //主线程函数 Thread::Thread(const ThreadFunc& func, const string& n)//构造函数,初始化线程 : started_(false), joined_(false), pthreadId_(0), tid_(new pid_t(0)), func_(func), name_(n) { setDefaultName(); } #ifdef __GXX_EXPERIMENTAL_CXX0X__ Thread::Thread(ThreadFunc&& func, const string& n) : started_(false), joined_(false), pthreadId_(0), tid_(new pid_t(0)), func_(std::move(func)), name_(n) { setDefaultName(); } #endif //主线程函数 Thread::~Thread()//如何子线程未完成,将其与父线程分离 { if (started_ && !joined_) { pthread_detach(pthreadId_); } } //主线程函数 //给线程对象命名 void Thread::setDefaultName() { int num = numCreated_.incrementAndGet();//原子操作 if (name_.empty()) { char buf[32]; snprintf(buf, sizeof buf, "Thread%d", num); name_ = buf; } } //主线程函数 void Thread::start()//开启线程 { assert(!started_); started_ = true; // FIXME: move(func_) detail::ThreadData* data = new detail::ThreadData(func_, name_, tid_); if (pthread_create(&pthreadId_, NULL, &detail::startThread, data)) { started_ = false; delete data; // or no delete? LOG_SYSFATAL << "Failed in pthread_create"; } } //主线程函数 int Thread::join()//线程阻塞 { assert(started_); //assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行 assert(!joined_); joined_ = true; return pthread_join(pthreadId_, NULL); }
Thread.h
// 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_THREAD_H #define MUDUO_BASE_THREAD_H #include <muduo/base/Atomic.h> #include <muduo/base/Types.h> #include <boost/function.hpp> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> #include <pthread.h> namespace muduo { class Thread : boost::noncopyable { public: typedef boost::function<void ()> ThreadFunc; explicit Thread(const ThreadFunc&, const string& name = string()); #ifdef __GXX_EXPERIMENTAL_CXX0X__ explicit Thread(ThreadFunc&&, const string& name = string()); #endif ~Thread(); void start();//开始 int join(); // return pthread_join() 阻塞 bool started() const { return started_; }//返回是否开始 // pthread_t pthreadId() const { return pthreadId_; } pid_t tid() const { return *tid_; }// const string& name() const { return name_; }//返回线程名 static int numCreated() { return numCreated_.get(); }//初始化numCreated private: void setDefaultName();//设置默认名 bool started_;//是否开始运行 bool joined_; //是否阻塞 pthread_t pthreadId_;//线程ID boost::shared_ptr<pid_t> tid_;//CurrentThread中的ID ThreadFunc func_;//线程函数 string name_;//线程名 static AtomicInt32 numCreated_;//初始化32位原子整数 }; } #endif
CurrentThread.h
// 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_CURRENTTHREAD_H #define MUDUO_BASE_CURRENTTHREAD_H #include <stdint.h> namespace muduo { namespace CurrentThread { // internal //记录当前线程信息 extern __thread int t_cachedTid; extern __thread char t_tidString[32]; extern __thread int t_tidStringLength; extern __thread const char* t_threadName; void cacheTid(); //得到当前线程ID inline int tid() { //性能优化,t_cachedTid==0 的情况很少发生。 if (__builtin_expect(t_cachedTid == 0, 0)) { cacheTid(); } return t_cachedTid; } inline const char* tidString() // for logging { return t_tidString; } inline int tidStringLength() // for logging { return t_tidStringLength; } //记录线程名字 inline const char* name() { return t_threadName; } //判断是否是主线程 bool isMainThread(); void sleepUsec(int64_t usec); } } #endif
相关文章推荐
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- [Muduo网络库源码分析] (5) base/FileUtil.cc_h_文件操作
- [Muduo网络库源码分析] (7) base/Singleton.h_SINGLETON对象创建型模式
- [Muduo网络库源码分析] (2) base/Condition.cc_h_条件变量操作
- [Muduo网络库源码分析] (3) base/CountDownLatch.cc_h_“倒计时门闩”同步
- [Muduo网络库源码分析] (4) base/Exception_cc_h_带 stack trace 的异常基类
- 【Java8源码分析】线程-Thread类的全面剖析
- Android之HandlerThread源码分析和简单使用(主线程和子线程通信、子线程和子线程通信)
- [Muduo网络库源码分析] (6) base/Mutex.h_互斥锁操作
- Netty学习之旅------再谈线程模型之源码分析NioEventLoopGroup、SingleThreadEventExecutor
- [Muduo网络库源码分析] (11) base/Types.h_基本类型声明
- Libevent源码分析-----evthread_notify_base通知主线程
- Muduo网络库源码分析(四)EventLoopThread和EventLoopThreadPool的封装
- EventBus源码解读详细注释(2)MainThread线程模型分析
- rt-thread的空闲线程源码分析
- Libevent源码分析-----evthread_notify_base通知主线程
- Libevent源码分析-----evthread_notify_base通知主线程
- [Muduo网络库源码分析] (8) base/StringPiece.h_字符串参数传递类型
- Libevent源码分析-----evthread_notify_base通知主线程
- lua 源码分析之线程对象lua_State