muduo库分析——base篇(4) Thread

线程管理对象,本身携带进程tid,需要执行的函数

头文件:

  typedef boost::function<void ()> ThreadFunc;	//无参数无返回线程函数

  explicit Thread(const ThreadFunc&, const string& name = string());	//别名防止拷贝函数

  CountDownLatch latch_;	//用于多线程等待满足条件后同时工作

  static AtomicInt32 numCreated_;	//原子计数器,记录线程个数


在CurrentThread命名空间中定义了线程私有资源,用于储存线程相关id,日志数据,名字等等


cpp文件:

namespace CurrentThread
{
  __thread int t_cachedTid = 0;		//线程私有资源,tid
  __thread char t_tidString[32];	
  __thread int t_tidStringLength = 6;	
  __thread const char* t_threadName = "unknown";
  const bool sameType = boost::is_same<int, pid_t>::value;	//判断是否int==pid_t
  BOOST_STATIC_ASSERT(sameType);
}
pid_t gettid()
{
  return static_cast<pid_t>(::syscall(SYS_gettid));		//获取当前pid(系统调用)
}

void afterFork()
{
	//调用Fork后的回调函数
  muduo::CurrentThread::t_cachedTid = 0;	//当前tid设为0,同时调用Fork的线程成为主线程
  //其他线程不会复制,锁的状态会复制
  muduo::CurrentThread::t_threadName = "main";
	//修改线程私有资源的当前tid
  CurrentThread::tid();
  // no need to call pthread_atfork(NULL, NULL, &afterFork);
}

class ThreadNameInitializer
{
 public:
  ThreadNameInitializer()
  {
	  //默认调用一次,同时设置好fork时函数(一般多线程不fork)
    muduo::CurrentThread::t_threadName = "main";
    CurrentThread::tid();
    pthread_atfork(NULL, NULL, &afterFork);
  }
};
ThreadNameInitializer init;//调用

struct ThreadData
{
	//每一个线程对象调用一个ThreadData,主要用于解耦,方便方法和数据绑定后传输
  typedef muduo::Thread::ThreadFunc ThreadFunc;
  ThreadFunc func_;
  string name_;
  pid_t* tid_;	//指针指向tid
  CountDownLatch* latch_;

  ThreadData(const ThreadFunc& func,
             const string& name,
             pid_t* tid,
             CountDownLatch* latch)
    : func_(func),
      name_(name),
      tid_(tid),
      latch_(latch)
  { }
void runInThread()
	  //指向tid后修改,再清零指针,内存已经修改好,线程对象仍然持有指针
void CurrentThread::cacheTid()	//储存一次tid
bool CurrentThread::isMainThread()//判断thread是否属于当前线程
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);
}
Thread::~Thread()
{
  if (started_ && !joined_)	//判断是否在运行中并且没有使用join
  {
    pthread_detach(pthreadId_);//线程运行后自动销毁(非阻塞)
  }
}
int num = numCreated_.incrementAndGet();	//原子加一后返回值
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))	//创建线程,将ThreadData进行绑定
  {
    started_ = false;
    delete data; // or no delete?
    LOG_SYSFATAL << "Failed in pthread_create";
  }
  else
  {
    latch_.wait();
    assert(tid_ > 0);
  }
}


多线程调用fork函数可能导致死锁,因为锁的状态会复制,但是线程只会复制调用fork的线程,其他线程不会复制



猜你喜欢

转载自blog.csdn.net/renhaopeng/article/details/80225154