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_H namespace 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());
}

单独编译后运行结果如下:

muduo网络库源码学习————线程类的更多相关文章

  1. muduo网络库源码学习————线程本地单例类封装

    muduo库中线程本地单例类封装代码是ThreadLocalSingleton.h 如下所示: //线程本地单例类封装 // Use of this source code is governed b ...

  2. muduo网络库源码学习————线程池实现

    muduo库里面的线程池是固定线程池,即创建的线程池里面的线程个数是一定的,不是动态的.线程池里面一般要包含线程队列还有任务队列,外部程序将任务存放到线程池的任务队列中,线程池中的线程队列执行任务,也 ...

  3. muduo网络库源码学习————线程特定数据

    muduo库线程特定数据源码文件为ThreadLocal.h //线程本地存储 // Use of this source code is governed by a BSD-style licens ...

  4. muduo网络库源码学习————日志类封装

    muduo库里面的日志使方法如下 这里定义了一个宏 #define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) ...

  5. muduo网络库源码学习————线程安全

    线程安全使用单例模式,保证了每次只创建单个对象,代码如下: Singleton.h // Use of this source code is governed by a BSD-style lice ...

  6. muduo网络库源码学习————Exception类

    Exception类是为异常捕获而设计,可以获得异常的信息以及栈的回溯信息 (原来的代码没有demangle成员函数,输出的格式比较难看,加了demangle成员函数,利用demangle成员函数可以 ...

  7. muduo网络库源码学习————Timestamp.cc

    今天开始学习陈硕先生的muduo网络库,moduo网络库得到很多好评,陈硕先生自己也说核心代码不超过5000行,所以我觉得有必要拿过来好好学习下,学习的时候在源码上面添加一些自己的注释,方便日后理解, ...

  8. muduo网络库源码学习————互斥锁

    muduo源码的互斥锁源码位于muduo/base,Mutex.h,进行了两个类的封装,在实际的使用中更常使用MutexLockGuard类,因为该类可以在析构函数中自动解锁,避免了某些情况忘记解锁. ...

  9. muduo网络库源码学习————日志滚动

    muduo库里面的实现日志滚动有两种条件,一种是日志文件大小达到预设值,另一种是时间到达超过当天.滚动日志类的文件是LogFile.cc ,LogFile.h 代码如下: LogFile.cc #in ...

随机推荐

  1. C/C++内存详解

    众所周知,堆和栈是数据结构中的两种数据结构类型,堆是一种具有优先顺序的完全二叉树(或者说是一种优先队列,因为它在一定的优先顺序下满足队列先进先出的特点),排队打饭就是它的典型实例,栈是一种后进先出的数 ...

  2. 37.3 net--TcpDemo1 大小写转换

    需求:使用TCP协议发送数据,并将接收到的数据转换成大写返回 启动方式:先打开服务端,再打开客户端 客户端 package day35_net_网络编程.tcp传输; import java.io.I ...

  3. String 对象-->substring() 方法

    1.定义和用法 substring() 方法用于提取两个指定下标之间的字符. substring() 方法返回的子串包括 开始 处的字符,但不包括 结束 处的字符 语法: string.substri ...

  4. python3(十九)Partial func

    # 偏函数(Partial function) # 如int()函数可以把字符串转换为整数,当仅传入字符串时,int()函数默认按十进制转换 # 但int()函数还提供额外的base参数,默认值为10 ...

  5. 【Java】【设计模式 Design Pattern】单例模式 Singleton

    什么是设计模式? 设计模式是在大量的实践中总结和理论化之后的最佳的类设计结构,编程风格,和解决问题的方式 设计模式已经帮助我们想好了所有可能的设计问题,总结在这些各种各样的设计模式当中,也成为GOF2 ...

  6. 转载:URL链接中的不同用处

    ,井号:表示网页中的一个位置,被称之为锚点,常用于某个网页间不同位置的跳转,简单的说就是在一个网页中,URL 不变的情况下,通过添加"#buy"的字符在 URL 最后可以跳转到当前 ...

  7. B. 蚂蚁觅食(二)

    B. 蚂蚁觅食(二) 单点时限: 1.0 sec 内存限制: 512 MB 一只饥饿的小蚂蚁外出觅食,幸运的的小蚂蚁发现了好多食物.但是这些食物位于一个N∗M的方格魔法阵的右下角,而小蚂蚁位于方格法阵 ...

  8. Oracle使用fy_recover_data恢复truncate删除的数据

    (一)truncate操作概述 在生产中,truncate是使用的多的命令,在使用不当的情况下,往往会造成表的数据全部丢失,恢复较为困难.对于truncate恢复,常见的有以下几种方法可以进行恢复: ...

  9. Xshell 中文提示乱码

    1.Alt+P 打开配置对话框,点击终端->编码,选择Unicode(utf-8)编码

  10. selenium 元素定位常用的方法

    元素定位的方法有2个 driver.findElement(By.args) 返回值是WebElement            //此方法是获取单一的页面元素 driver.findElements ...