[Muduo网络库源码分析] (9) base/Thread.cc_h_CurrentThread_h线程对象

来源:互联网 发布:java执行vbs 编辑:程序博客网 时间:2024/06/05 10:58

线程对象

实现:实现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
阅读全文
0 0
原创粉丝点击