muduo库源码学习(base)Thread和CurrentThread

16 篇文章 0 订阅

//CurrentThread,定义了一些辅助函数

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();

  inline int tid()
  {
    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);
}
}

//Thread.h&&cpp
namespace muduo
{
//线程对象
//主线程开启一个在新线程的工作,代表这个新线程的对象就是Thread,它很显然留在了主线程,而在
//它的start()里,显然需要完成以下任务:计算自己的线程id,线程名,保存所属主线程,运行主线程传递来的func
class Thread : noncopyable
{
 public:
  typedef std::function<void ()> ThreadFunc;//线程工作函数类型

  explicit Thread(ThreadFunc, const string& name = string());//这里更新,以前用的是ThreadFunc&,现在是拷贝然后move
  // FIXME: make it movable in C++11
  ~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_; }//返回线程的系统id
  const string& name() const { return name_; }

  static int numCreated() { return numCreated_.get(); }

 private:
  void setDefaultName();//在线程的构造函数里使用

  bool       started_;
  bool       joined_;
  pthread_t  pthreadId_;//同一进程里的不同线程号,用于区分线程,回收后可重复使用
  pid_t      tid_;//内核里的线程/进程id
  ThreadFunc func_;//工作函数
  string     name_;
  CountDownLatch latch_;//计数器,C++17版新增

  static AtomicInt32 numCreated_;
};

}

namespace muduo
{
namespace CurrentThread//线程局部变量
{
  __thread int t_cachedTid = 0;//pid_t就是int
  __thread char t_tidString[32];
  __thread int t_tidStringLength = 6;
  __thread const char* t_threadName = "unknown";
  static_assert(std::is_same<int, pid_t>::value, "pid_t should be int");//让编译器检查int和pid_t是同类型
}

namespace detail
{
	//::syscall(SYS_gettid)得到线程id
pid_t gettid()
{
  return static_cast<pid_t>(::syscall(SYS_gettid));
}
//fork之后 先将t_cachedTid = 0,改线程名,调用函数重新计算tid
void afterFork()
{
  muduo::CurrentThread::t_cachedTid = 0;
  muduo::CurrentThread::t_threadName = "main";
  CurrentThread::tid();
  // no need to call pthread_atfork(NULL, NULL, &afterFork);
}
//有了这个类
class ThreadNameInitializer
{
 public:
  ThreadNameInitializer()
  {
    muduo::CurrentThread::t_threadName = "main";
    CurrentThread::tid();
	//#include <pthread.h>
	//int pthread_atfork(void(*prepare)(void), void(*parent)(void), void(*child)(void));
	//pthread_atfork()在fork()之前调用,当调用fork时,内部创建子进程前在父进程中会调用prepare,
	//内部创建子进程成功后,父进程会调用parent ,子进程会调用child。
    pthread_atfork(NULL, NULL, &afterFork);//相当于给子进程的回掉函数
  }
};

ThreadNameInitializer init;//全局变量,初始化就为主线程生成线程信息

//线程数据,线程A将它传送到新开启的线程B,然后A调用函数startThread开启B线程任务,B更新线程信息后执行A传递的func
struct ThreadData
{
  typedef muduo::Thread::ThreadFunc ThreadFunc;
  ThreadFunc func_;
  string name_;
  pid_t* tid_;
  CountDownLatch* latch_;

  ThreadData(ThreadFunc func,
             const string& name,
             pid_t* tid,
             CountDownLatch* latch)
    : func_(std::move(func)),
      name_(name),
      tid_(tid),
      latch_(latch)
  { }
  //ThreadData具体的执行
  void runInThread()
  {
    *tid_ = muduo::CurrentThread::tid();//计算本线程id,保存在线程局部变量里
    tid_ = NULL;//然后。。。没用了
    latch_->countDown();// latch_是主线程传递过来的,主线程等待从线程减少技术
    latch_ = NULL;//没用了

    muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str();
    ::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName);
    try
    {
      func_();
      muduo::CurrentThread::t_threadName = "finished";
    }
    catch (const 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());
      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
    }
  }
};
//父线程交给系统的回调,obj是父线程传递的threadData
void* startThread(void* obj)
{
  ThreadData* data = static_cast<ThreadData*>(obj);
  data->runInThread();
  delete data;
  return NULL;
}

}
}

using namespace muduo;

void CurrentThread::cacheTid()
{
  if (t_cachedTid == 0)//为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 };//秒+纳秒
  //s,ms,us,ns都是1:1000
  ts.tv_sec = static_cast<time_t>(usec / Timestamp::kMicroSecondsPerSecond);// us/1000000
  ts.tv_nsec = static_cast<long>(usec % Timestamp::kMicroSecondsPerSecond * 1000);//%取秒之后的数,再转化成us
  ::nanosleep(&ts, NULL);
}

AtomicInt32 Thread::numCreated_;//这是静态变量

Thread::Thread(ThreadFunc func, const string& n)
  : started_(false),
    joined_(false),
    pthreadId_(0),
    tid_(0),
    func_(std::move(func)),//forC++17
    name_(n),
    latch_(1)
{
  setDefaultName();
}

Thread::~Thread()
{
  if (started_ && !joined_)
  {
    pthread_detach(pthreadId_);//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_, &latch_);
  if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))//如果开启失败
  {
    started_ = false;
    delete data; // or no delete?
    LOG_SYSFATAL << "Failed in pthread_create";
  }
  else
  {
    latch_.wait();
    assert(tid_ > 0);
  }//子线程已经开始运行了~~
}

int Thread::join()
{
  assert(started_);
  assert(!joined_);
  joined_ = true;
  return pthread_join(pthreadId_, NULL);//pthreadId_,
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值