线程管理对象,本身携带进程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的线程,其他线程不会复制