muduo网络库源码学习————线程类
来源:互联网 发布:js 单选框的选中事件 编辑:程序博客网 时间:2024/05/23 02:03
muduo库里面的线程类是使用基于对象的编程思想,源码目录为muduo/base,如下所示:
线程类头文件:
// 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 <pthread.h>//线程类头文件namespace muduo{class Thread : boost::noncopyable{ public: typedef boost::function<void ()> ThreadFunc;//函数适配接收的函数//线程构造函数,参数为回调函数和线程名称 explicit Thread(const ThreadFunc&, const string& name = string());//名称默认值为空的字符串类//线程析构函数 ~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_; }//线程的真实pid const string& name() const { return name_; }//线程的名称 static int numCreated() { return numCreated_.get(); }//已经启动的线程个数 private: static void* startThread(void* thread);//现成的入口函数,调用runInThread函数 void runInThread();//调用回调函数func_ bool started_;//线程是否已经启动 pthread_t pthreadId_;//线程的pthread_t pid_t tid_;//线程真实的 pid ThreadFunc func_;//线程的回调函数 string name_;//线程的名称 static AtomicInt32 numCreated_;//已经创建的线程的个数,每当创建一个线程,该值就加一(原子整数类)};}#endif
线程类的实现文件:
// 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 <errno.h>#include <stdio.h>#include <unistd.h>#include <sys/syscall.h>#include <sys/types.h>#include <linux/unistd.h>namespace muduo{namespace CurrentThread{//__thread两个下划线是gcc 内置的线程局部存储设施//每个线程各有一个,并不会去共享他//缓存获取tid是为了提高获取tid的效率 __thread int t_cachedTid = 0;//线程真实pid的缓存,如果每次都用系统调用去获取pid,效率会低 __thread char t_tidString[32];//tid的字符串表示形式 __thread const char* t_threadName = "unknown";//线程的名称 const bool sameType = boost::is_same<int, pid_t>::value;//如果是相同类型,返回true BOOST_STATIC_ASSERT(sameType);//编译时断言}namespace detail{pid_t gettid()//通过系统调用SYS_gettid获得tid{ return static_cast<pid_t>(::syscall(SYS_gettid));//类型转化为pid_t}void afterFork()//子进程调用的{ muduo::CurrentThread::t_cachedTid = 0;//当前线程pid赋值0 muduo::CurrentThread::t_threadName = "main";//名称赋值name CurrentThread::tid();//进行缓存 // no need to call pthread_atfork(NULL, NULL, &afterFork);}class ThreadNameInitializer{ public: ThreadNameInitializer()//构造函数 { muduo::CurrentThread::t_threadName = "main";//线程名称赋为main,即为主线程名称 CurrentThread::tid();//缓存当前线程的pid //#include <pthread.h> //int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void)); //调用fork时,内部创建子进程前在父进程中会调用prepare, //内部创建子进程成功后,父进程会调用parent ,子进程会调用child pthread_atfork(NULL, NULL, &afterFork);//如果使用fork函数,那么子进程会调用邋afterFork }};ThreadNameInitializer init;}}using namespace muduo;void CurrentThread::cacheTid(){ if (t_cachedTid == 0) { t_cachedTid = detail::gettid();//调用gettid函数获得tid int n = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);//将tid格式化保存在t_tidString中 assert(n == 6);//断言长度是6,5d后面还有一个空格,所以是6 (void) n;//这一句主要是预防n没有使用从而产生警告 }}bool CurrentThread::isMainThread(){ return tid() == ::getpid();//查看tid是否等于当前进程id}AtomicInt32 Thread::numCreated_;//构造函数,初始化Thread::Thread(const ThreadFunc& func, const string& n) : started_(false), pthreadId_(0),tid_(0),func_(func),name_(n){ numCreated_.increment();//创建的线程的个数加一,为原子性操作}Thread::~Thread(){ // no join}void Thread::start(){ assert(!started_); started_ = true; //创建线程,startThread为线程的入口函数 errno = pthread_create(&pthreadId_, NULL, &startThread, this); if (errno != 0) {//日志 // LOG_SYSFATAL << "Failed in pthread_create"; }}int Thread::join(){ assert(started_); return pthread_join(pthreadId_, NULL);}//线程的入口函数void* Thread::startThread(void* obj){//this指针传到obj Thread* thread = static_cast<Thread*>(obj);//转化为线程基类的指针 thread->runInThread();//调用线程函数runInThread return NULL;}//被线程的入口函数调用void Thread::runInThread(){ tid_ = CurrentThread::tid();//获取线程的tid muduo::CurrentThread::t_threadName = name_.c_str();//缓存该线程的名称 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 }}
CurrentThread头文件
// 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_Hnamespace muduo{//CurrentThread的名称空间namespace CurrentThread{ // internal extern __thread int t_cachedTid; extern __thread char t_tidString[32]; extern __thread const char* t_threadName; void cacheTid(); inline int tid() { if (t_cachedTid == 0)//还没有缓存过 {//t_cachedTid初值 是0 cacheTid();//进行缓存 } return t_cachedTid;//返回缓存的tid } inline const char* tidString() // for logging { return t_tidString;//返回tid的字符串表示形式 } inline const char* name() { return t_threadName;//返回线程名称 } bool isMainThread();//是否是主线程}}#endif
测试代码位于muduo/base/tests
//线程测试程序#include <muduo/base/Thread.h>#include <muduo/base/CurrentThread.h>#include <string>#include <boost/bind.hpp>#include <stdio.h>void threadFunc(){ printf("tid=%d\n", muduo::CurrentThread::tid());}void threadFunc2(int x){ printf("tid=%d, x=%d\n", muduo::CurrentThread::tid(), x);}class Foo{ public: explicit Foo(double x) : x_(x) { } void memberFunc() { printf("tid=%d, Foo::x_=%f\n", muduo::CurrentThread::tid(), x_); } void memberFunc2(const std::string& text) { printf("tid=%d, Foo::x_=%f, text=%s\n", muduo::CurrentThread::tid(), x_, text.c_str()); } private: double x_;};int main(){//获取当前线程的pid(进程id 线程pid) printf("pid=%d, tid=%d\n", ::getpid(), muduo::CurrentThread::tid());//创建一个线程对象,传递一个函数 muduo::Thread t1(threadFunc); t1.start();//启动线程 t1.join();//threadFunc2带了一个参数,用boost::bind函数传递进去,最后是线程的名称,可以不传 muduo::Thread t2(boost::bind(threadFunc2, 42), "thread for free function with argument"); t2.start(); t2.join();//创建一个对象 Foo foo(87.53);//创建第三个线程(成员函数的话一定要用&) muduo::Thread t3(boost::bind(&Foo::memberFunc, &foo), "thread for member function without argument"); t3.start(); t3.join();//创建第四个线程,这里传进去的函数是带参数的 muduo::Thread t4(boost::bind(&Foo::memberFunc2, boost::ref(foo), std::string("Shuo Chen"))); t4.start(); t4.join();//打印最后创建的线程总数 printf("number of created threads %d\n", muduo::Thread::numCreated());}
单独编译后运行结果如下:
0 0
- muduo网络库源码学习————线程类
- muduo网络库源码学习————线程池实现
- muduo网络库源码学习————线程安全
- muduo网络库源码学习————线程特定数据
- muduo网络库源码学习————线程本地单例类封装
- muduo网络库源码学习————互斥锁
- muduo网络库源码学习————Exception类
- muduo网络库源码学习————日志类封装
- muduo网络库源码学习————Timestamp.cc
- muduo网络库源码学习————原子性操作Atomic.h
- muduo网络库源码学习————条件变量
- muduo网络库源码学习————无界队列和有界队列
- muduo网络库源码学习————日志滚动
- [Muduo网络库源码分析] (10) base/ThreadPoll_cc_h_线程池
- muduo库阅读(5)——线程
- muduo库阅读(6)——当前线程
- muduo库阅读(7)——线程本地存储
- muduo库阅读(9)——线程池
- 汇总常见的JAVA错误
- HDU Boring counting 4358 莫队算法
- AArch64简介
- 高斯密度的贝叶斯分类
- 1039 -- 单目标0/1背包问题
- muduo网络库源码学习————线程类
- django 1.8 官方文档翻译: 6-6-4 部署静态文件
- java综合(六)hibernate.current_session_context_class配置
- Android开发个人
- win7下安装sourcetree
- 1040 -- 用动态规划求解矩阵乘法链问题
- Leetcode全排列问题Java版
- 模拟洗牌程序
- CodeForces 387C George and Number