13muduo_base库源码分析(四)
1.线程标识符
2.Thread类图
typedefboost::function<void ()>ThreadFunc;
__threadstring t_obj1(“cppcourse”); //错误,不能调用对象的构造函数
__threadstring* t_obj2 = new string; //错误,初始化只能是编译期常量
__threadstring* t_obj3 = NULL; //正确
线程特定属性tsd,可以修饰非POD类型
boost::is_same判断类型是否为同一类型
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/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_; }const string& name() const { return name_; }static int numCreated() { return numCreated_.get(); }private:static void* startThread(void* thread);void runInThread();bool started_;pthread_t pthreadId_;pid_t tid_;ThreadFunc func_;string name_;static AtomicInt32 numCreated_;
};}
#endif
CurrentThread.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_CURRENTTHREAD_H
#define MUDUO_BASE_CURRENTTHREAD_Hnamespace muduo
{
namespace CurrentThread
{// internalextern __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){cacheTid();}return t_cachedTid;}inline const char* tidString() // for logging{return t_tidString;}inline const char* name(){return t_threadName;}bool isMainThread();
}
}#endif
Thread.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 <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修饰的变量是线程局部存储的。__thread int t_cachedTid = 0; // 线程真实pid(tid)的缓存,// 是为了减少::syscall(SYS_gettid)系统调用的次数// 提高获取tid的效率__thread char t_tidString[32]; // 这是tid的字符串表示形式__thread const char* t_threadName = "unknown";const bool sameType = boost::is_same<int, pid_t>::value;BOOST_STATIC_ASSERT(sameType);
}namespace detail
{pid_t gettid()
{return static_cast<pid_t>(::syscall(SYS_gettid));
}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);}
};ThreadNameInitializer init;
}
}using namespace muduo;void CurrentThread::cacheTid()
{if (t_cachedTid == 0){t_cachedTid = detail::gettid();int n = snprintf(t_tidString, sizeof t_tidString, "%5d ", t_cachedTid);assert(n == 6); (void) n;}
}bool CurrentThread::isMainThread()
{return tid() == ::getpid();
}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;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)
{Thread* thread = static_cast<Thread*>(obj);thread->runInThread();return NULL;
}void Thread::runInThread()
{tid_ = CurrentThread::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}
}
Thread_test.cc
#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()
{printf("pid=%d, tid=%d\n", ::getpid(), muduo::CurrentThread::tid());muduo::Thread t1(threadFunc);t1.start();t1.join();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());
}
3.pthread_atfork
1.死锁示例
// 一个在多线程程序里fork造成死锁的例子
// 一个输出示例:
/*pid = 19445 Entering main ...
pid = 19445 begin doit ...
pid = 19447 begin doit ...
pid = 19445 end doit ...
pid = 19445 Exiting main ...父进程在创建了一个线程,并对mutex加锁,
父进程创建一个子进程,在子进程中调用doit,由于子进程会复制父进程的内存,这时候mutex处于锁的状态,
父进程在复制子进程的时候,只会复制当前线程的执行状态,其它线程不会复制。因此子进程会处于死锁的状态。
*/
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* doit(void* arg)
{printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));pthread_mutex_lock(&mutex);struct timespec ts = {2, 0};nanosleep(&ts, NULL);pthread_mutex_unlock(&mutex);printf("pid = %d end doit ...\n",static_cast<int>(getpid()));return NULL;
}int main(void)
{printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));pthread_t tid;pthread_create(&tid, NULL, doit, NULL);struct timespec ts = {1, 0};nanosleep(&ts, NULL);if (fork() == 0){doit(NULL);}pthread_join(tid, NULL);printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));return 0;
}
2.无死锁
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;void* doit(void* arg)
{printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));pthread_mutex_lock(&mutex);struct timespec ts = {2, 0};nanosleep(&ts, NULL);pthread_mutex_unlock(&mutex);printf("pid = %d end doit ...\n",static_cast<int>(getpid()));return NULL;
}void prepare(void)
{pthread_mutex_unlock(&mutex);
}void parent(void)
{pthread_mutex_lock(&mutex);
}int main(void)
{pthread_atfork(prepare, parent, NULL);printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));pthread_t tid;pthread_create(&tid, NULL, doit, NULL);struct timespec ts = {1, 0};nanosleep(&ts, NULL);if (fork() == 0){doit(NULL);}pthread_join(tid, NULL);printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));return 0;
}
3.pthread_atfork示例
#include <stdio.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>void prepare(void)
{printf("pid = %d prepare ...\n", static_cast<int>(getpid()));
}void parent(void)
{printf("pid = %d parent ...\n", static_cast<int>(getpid()));
}void child(void)
{printf("pid = %d child ...\n", static_cast<int>(getpid()));
}int main(void)
{printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));pthread_atfork(prepare, parent, child);fork();printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));return 0;
}
13muduo_base库源码分析(四)相关推荐
- 【投屏】Scrcpy源码分析四(最终章 - Server篇)
Scrcpy源码分析系列 [投屏]Scrcpy源码分析一(编译篇) [投屏]Scrcpy源码分析二(Client篇-连接阶段) [投屏]Scrcpy源码分析三(Client篇-投屏阶段) [投屏]Sc ...
- 《微信小程序-进阶篇》Lin-ui组件库源码分析-列表组件List(一)
大家好,这是小程序系列的第二十篇文章,在这一个阶段,我们的目标是 由简单入手,逐渐的可以较为深入的了解组件化开发,从本文开始,将记录分享lin-ui的源码分析,期望通过对lin-ui源码的学习能加深组 ...
- Android主流三方库源码分析(九、深入理解EventBus源码)
一.EventBus使用流程概念 1.Android事件发布/订阅框架 2.事件传递既可用于Android四大组件间通信 3.EventBus的优点是代码简洁,使用简单,事件发布.订阅充分解耦 4.首 ...
- ABP源码分析四十七:ABP中的异常处理
ABP源码分析四十七:ABP中的异常处理 参考文章: (1)ABP源码分析四十七:ABP中的异常处理 (2)https://www.cnblogs.com/1zhk/p/5538983.html (3 ...
- gSOAP 源码分析(四)
gSOAP 源码分析(四) 2012-6-2 邵盛松 前言 本文主要说明gSOAP中对Client的认证分析 gSOAP中包含了HTTP基本认证,NTLM认证等,还可以自定义SOAP Heard实现认 ...
- Spring 源码分析(四) ——MVC(二)概述
随时随地技术实战干货,获取项目源码.学习资料,请关注源代码社区公众号(ydmsq666) from:Spring 源码分析(四) --MVC(二)概述 - 水门-kay的个人页面 - OSCHINA ...
- surprise库源码分析
最近工作上需要使用到协同过滤,来计算相似度,因此根据https://blog.csdn.net/weixin_43849063/article/details/111500236的步骤对surpris ...
- 【转】ABP源码分析四十七:ABP中的异常处理
ABP 中异常处理的思路是很清晰的.一共五种类型的异常类. AbpInitializationException用于封装ABP初始化过程中出现的异常,只要抛出AbpInitializationExce ...
- 【转】ABP源码分析四:Configuration
核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...
最新文章
- 2019计算与系统神经科学大会Cosyne 前沿研究汇总
- android 拍照不能保存图片格式,Android 拍照后保存到手机里,在相册找不到
- spark.mllib:回归算法
- 【vue】跟着老马学习vue-数据双向绑定
- 开源推荐:.Net Core3.1 + EF Core + LayUI 封装的MVC版后台管理系统
- Java学习笔记(基本数据类型和变量命名规则)
- 计算机专业应届生年薪30多万,制造焦虑,非广告,请看截图
- 基于JAVA+SpringMVC+Mybatis+MYSQL的田径运动会管理系统
- .NET组件程序设计0723
- mysql巡检常用命令_总结Linux下系统巡检常用命令
- while 循环 格式化输出
- Flutter高级第3篇:底部 Tab 切换保持页面状态的几种方法
- 20. 远程端口查看
- Matlab将double类型转换为正整数类型
- VS2005下配置OGRE
- 面部捕捉技术_FT45面部表情捕捉系统--说明书(中文版)
- 你在工作中遇到了哪些问题,解决办法是什么
- 工作日志之Sonar扫描错误处理-Sonar扫描结果入库 java.sql.BatchUpdateException: Incorrect string value: '\xF3\xA3\xAC\xB
- Win32窗口程序实例
- java 24字母_java 时间格式化中的模式字母