muduo之Thread
生活随笔
收集整理的这篇文章主要介绍了
muduo之Thread
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
muduo也对线程进行了封装,下面看一下实现。
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/CountDownLatch.h" #include "muduo/base/Types.h"#include <functional> #include <memory> #include <pthread.h>namespace muduo {class Thread : noncopyable {public:typedef std::function<void ()> ThreadFunc;explicit Thread(ThreadFunc, const string& name = string());// 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_; }const string& name() const { return name_; }static int numCreated() { return numCreated_.get(); }private:void setDefaultName();bool started_; //线程是否启动bool joined_; //线程是否回收pthread_t pthreadId_;//线程IDpid_t tid_; //进程idThreadFunc func_;//线程回调函数string name_; //线程名称CountDownLatch latch_;static AtomicInt32 numCreated_;//原子操作 };} // namespace muduo #endif // MUDUO_BASE_THREAD_HThread.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 <type_traits>#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 detail {pid_t gettid() //获取线程的进程ID {return static_cast<pid_t>(::syscall(SYS_gettid)); //真实的线程ID(不同进程中的线程ID可能相同)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();pthread_atfork(NULL, NULL, &afterFork);/*pthread_atfork(void (*prepare)(void),void (*parent)(void), void(*child)(void))prepare在父进程fork创建子进程之前调用,这里可以获取父进程定义的所有锁;child fork返回之前在子进程环境中调用,在这里unlock prepare获得的锁;parent fork创建了子进程以后,但在fork返回之前在父进程的进程环境中调用的,在这里对prepare获得的锁进行解锁*/} };ThreadNameInitializer init;//C++中class和struct一样,只是权限的区别 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), //将tid缓存起来latch_(latch){ }void runInThread(){*tid_ = muduo::CurrentThread::tid();//调用tid()该tid已被缓存起来tid_ = NULL;latch_->countDown();latch_ = NULL;muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str();::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName);//prctl设置线程的名字try{func_();//运行线程运行函数muduo::CurrentThread::t_threadName = "finished";}catch (const Exception& ex)//Exception异常{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; }} // namespace detailvoid 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();//通过线程的pid和进程的pid做比较如果相同说明是主线程 }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(ThreadFunc func, const string& n): started_(false),joined_(false),pthreadId_(0),tid_(0),func_(std::move(func)),name_(n),latch_(1) {setDefaultName();//设置默认的名字 }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_, &latch_);if (pthread_create(&pthreadId_, NULL, &detail::startThread, data))//pthread_create成功返回0{started_ = false;delete data; // or no delete?LOG_SYSFATAL << "Failed in pthread_create";}else{//如果线程创建成功,主线程阻塞在这里,等待子线程执行threadFunc之前被唤醒latch_.wait();assert(tid_ > 0);} }int Thread::join() {assert(started_);assert(!joined_);joined_ = true;return pthread_join(pthreadId_, NULL); }} // namespace muduo
总结
以上是生活随笔为你收集整理的muduo之Thread的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: muduo之ThreadLocal
- 下一篇: muduo之ThreadPool