muduo网络库剖析——线程Thread类

news2024/11/15 17:50:21

muduo网络库剖析——线程Thread类

  • 前情
    • 从muduo到my_muduo
  • 概要
  • 框架与细节
    • 成员
    • 函数
    • 使用方法
  • 源码
  • 结尾

前情

从muduo到my_muduo

作为一个宏大的、功能健全的muduo库,考虑的肯定是众多情况是否可以高效满足;而作为学习者,我们需要抽取其中的精华进行简要实现,这要求我们足够了解muduo库。

做项目 = 模仿 + 修改,不要担心自己学了也不会写怎么办,重要的是积累,学到了这些方法,如果下次在遇到通用需求的时候你能够回想起之前的解决方法就够了。送上一段话!

在这里插入图片描述

概要

Thread类实际上是对应的one loop one thread中的thread,那么相应的thread也有自己的一些成员与函数。

框架与细节

成员

在这里插入图片描述
首先thread也有判断是否已经启动的状态位started,以及是否和父进程分离开来的状态位。以及用RAII机制来给thread进行资源管理。因为允许thread被多个对象指,所以对应的是共享指针而不是独享指针。接着是thread的线程号,这个是用来判断one loop one thread的。还有线程执行函数func_,线程的名字,有多少个线程被创建了。这个值不是单个线程独享的,所以定义为static静态变量,为了确保线程安全性,使用原子数据类型atomic_int。

在这里插入图片描述
对于atomic_int的初始化,首先肯定是在类外进行初始化的。但是这里因为atomic_int的拷贝构造函数默认是delete的,所以我们只能用构造函数的方式去初始化而不能用拷贝构造函数的方式去初始化。因此是numCreated_(0),而不是numCreated_ = 0.

函数

在这里插入图片描述
接下来是,Thread的构造函数实现。传参肯定需要线程执行函数回调,以及线程名字。并且调用设置默认名字函数。func_使用右值赋值。

在这里插入图片描述
在设置默认名字函数内,我们同时进行对线程创建数目的增加统计,如果传入的线程名字为空,就给默认的线程名字,否则就是传入的线程名。

在这里插入图片描述
接下来是线程类的析构函数,首先得先确认状态,如果是开始态,并且线程没有被分离,则线程需要分离,就调用thread自带的分离函数进行分离。

在这里插入图片描述
首先将thread启动状态位置成true。既然要启动,肯定需要让一个新线程启动起来。对与指向thread的共享智能指针,给它赋值的方式是new一个堆上的空间。因此使用shared_ptr< thread >(new thread());来创建新线程,并将指针赋给thread_。对于thread,他的创建方式这里采用c++11中的匿名函数。引用捕获变量,在匿名函数体内,我们需要记录此时的线程号。这里的好处类的作用域能够进入到新线程里,所以tid_不需要加类域。可以学习一下这种写法。除此以外,我们还要在线程中执行线程的执行回调函数。另外一个重点是,为了在start函数结束之后,tid已经是确定值,我们使用一个线程同步的方式来保证指令执行的顺序。所以我们使用了一个sem信号量。信号量的初始值是0,这样必须要等到信号量post之后才能wait到信号量。对于sem_init,第二个参数是询问是否需要用到sem给到的默认初始值,选择false就需要初始化第三个参数。

在这里插入图片描述

线程的分离也需要单独创建函数,其中将线程的状态位置1,并调用thread自带的join分离函数即可。

在这里插入图片描述
另外,定义一个CurrentThread的命名空间,其中实现了查询现在的线程的id是多少,封装在里面的是一个系统调用,大家可以学习一下。

使用方法

源码

//Thread.h
#pragma once

#include <sys/syscall.h>
#include <unistd.h>
#include <iostream>
#include <string>
#include <memory>
#include <thread>

namespace CurrentThread {
    int t_cachedTid = 0;
    inline int tid() {
        if (t_cachedTid == 0) {
            t_cachedTid = static_cast<pid_t>(::syscall(SYS_gettid));
        }
        return t_cachedTid;
    }
};

class Thread : noncopyable
{
public:
    using ThreadFunc = std::function<void()>;

    explicit Thread(ThreadFunc, const std::string &name = std::string());
    ~Thread();

    void start();
    void join();

    bool started() const { return started_; }
    pid_t tid() const { return tid_; }
    const std::string& name() const { return name_; }

    static int numCreated() { return numCreated_; }
private:
    void setDefaultName();

    bool started_;
    bool joined_;
    std::shared_ptr<std::thread> thread_;
    pid_t tid_;
    ThreadFunc func_;
    std::string name_;
    static std::atomic_int numCreated_;
};

//Thread.cc
#include <semaphore.h>

#include "Thread.h"

std::atomic_int Thread::numCreated_(0);

Thread::Thread(ThreadFunc func, const std::string &name)
    : started_(false)
    , joined_(false)
    , tid_(0)
    , func_(std::move(func))
    , name_(name) {
    setDefaultName();
}

Thread::~Thread() {
    if (started_ && !joined_)
    {
        thread_->detach(); // thread类提供的设置分离线程的方法
    }
}

// 一个Thread对象,记录的就是一个新线程的详细信息 
void Thread::start() {
    started_ = true;
    sem_t sem;
    sem_init(&sem, false, 0);

    // 开启线程
    thread_ = std::shared_ptr<std::thread>(new std::thread([&](){
        // 获取线程的tid值
        tid_ = CurrentThread::tid();
        sem_post(&sem);
        // 开启一个新线程,专门执行该线程函数
        func_(); 
    }));

    // 这里必须等待获取上面新创建的线程的tid值
    sem_wait(&sem);
}

void Thread::join() {
    joined_ = true;
    thread_->join();
}

void Thread::setDefaultName() {
    int num = ++numCreated_;
    if (name_.empty())
    {
        char buf[32] = {0};
        snprintf(buf, sizeof buf, "Thread%d", num);
        name_ = buf;
    }
}

结尾

以上就是线程Thread类的相关介绍,以及我在进行项目重写的时候遇到的一些问题,和我自己的一些心得体会。发现写博客真的会记录好多你的成长,而且对于一个好的项目,写博客也是证明你确实有过深度思考,并且在之后面试或者工作时遇到同样的问题能够进行复盘的一种有效的手段。所以,希望uu们也可以像我一样,养成写博客的习惯,逐渐脱离菜鸡队列,向大佬前进!!!加油!!!

也希望我能够完成muduo网络库项目的深度学习与重写,并在功能上能够拓展。也希望在完成这个博客系列之后,能够引导想要学习muduo网络库源码的人,更好地探索这篇美丽繁华的土壤。致敬chenshuo大神!!!

鉴于博主只是一名平平无奇的大三学生,没什么项目经验,所以可能很多东西有所疏漏,如果有大神发现了,还劳烦您在评论区留言,我会努力尝试解决问题!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1404259.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CentOS7安装Docker和docekr-compose

CentOS7安装Docker Docker 分为 CE 和 EE 两大版本。CE免费版&#xff0c;EE付费版 Docker CE 支持 64 位版本 CentOS 7&#xff0c;并且要求内核版本不低于 3.10 第一步、检测系统环境 如果之前或者安装系统时候自带docker的话可以卸载&#xff08;可选&#xff09; 如果之…

用ChatGPT教学、科研!亚利桑那州立大学与OpenAI合作

亚利桑那州立大学&#xff08;简称“ASU”&#xff09;在官网宣布与OpenAI达成技术合作。从2024年2月份开始&#xff0c;为所有学生提供ChatGPT企业版访问权限&#xff0c;主要用于学习、课程作业和学术研究等。 为了帮助学生更好地学习ChatGPT和大语言模型产品&#xff0c;AS…

Linux下软件安装的命令【RPM,YUM】及常用服务安装【JDK,Tomcat,MySQL】

Linux下软件安装的命令 源码安装 以源代码安装软件&#xff0c;每次都需要配置操作系统、配置编译参数、实际编译&#xff0c;最后还要依据个人喜好的方式来安装软件。这个过程很麻烦很累人。 RPM软件包管理 RPM安装软件的默认路径: 注意&#xff1a; /etc 配置文件放置目录…

基于Java SSM框架实现共享单车管理系统项目【项目源码+论文说明】

基于java的SSM框架实现共享单车管理系统演示 摘要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于共享单车管理系统当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了…

鸿蒙自定义刷新组件使用

前言 DevEco Studio版本&#xff1a;4.0.0.600 1、RefreshLibrary_HarmonyOS.har&#xff0c;用于HarmonyOS "minAPIVersion": 9, "targetAPIVersion": 9, "apiReleaseType": "Release", "compileSdkVersion": "3.…

核苷酸与相对论的数学关系猜想

质量-鸟嘌呤 M-G 金 收缩 能量-胸腺嘧啶 E-T 火 混沌 时间-胞嘧啶 T-C 水 次序 空间-腺嘌呤 S-A 木 扩散 确定了这三种对应关系之后&#xff0c;我们就可以用相对论里面的数学关系来确定基因的关系 四边形理论有六个方…

python24.1.22创建类-定义对象属性

类&#xff1a;创建对象的模板&#xff0c;定义对象的属性和方法 对象&#xff1a;类的实例 Pascal命名法定义类名称 定义类 创建对象 返回对象属性

【百面机器学习】读书笔记(一)

本文系列主要作用就是读书笔记&#xff0c;自己看的话比较杂&#xff0c;没怎么归类过&#xff0c;所以现在跟着这个分类走一遍。本文主要内容为前两章&#xff0c;特征工程和模型评估。 如果我想起一些相关的内容也会做适当的补充&#xff0c;主打就是一个intuition&#xff…

基于XG24-EK2703A的BLE HID蓝牙键盘+鼠标复合设备功能开发(BLE+HID+FreeRTOS+Gecko SDK)

目录 项目介绍硬件介绍项目设计开发环境及工程参考总体流程图硬件基本配置应用初始化按键中断回调定时器回调按键响应任务蓝牙事件回调BLE HIDReport Map及报文键盘设备鼠标设备复合设备 发送字符串上/下滚动 功能展示项目总结 &#x1f449; 【Funpack3-1】基于XG24-EK2703A的…

Django后台列表显示图片

在列表中显示ImageField的图片预览 编辑应用的models.py&#xff0c;添加下面代码&#xff1a; class Product(models.Model):# ...image models.ImageField(upload_toproducts/%Y/%m/%d, blankTrue)def image_data(self):if self.image:return format_html(<img src"…

2017年认证杯SPSSPRO杯数学建模B题(第二阶段)岁月的印记全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 B题 岁月的印记 原题再现&#xff1a; 对同一个人来说&#xff0c;如果没有过改变面容的疾病、面部外伤或外科手术等经历&#xff0c;年轻和年老时的面容总有很大的相似性。人们在生活中也往往能够分辨出来两张不同年龄段的照片是不是同一个人…

Elasticsearch:介绍 kNN query,这是进行 kNN 搜索的专家方法

作者&#xff1a;来自 Elastic Mayya Sharipova, Benjamin Trent 当前状况&#xff1a;kNN 搜索作为顶层部分 Elasticsearch 中的 kNN 搜索被组织为搜索请求的顶层&#xff08;top level&#xff09;部分。 我们这样设计是为了&#xff1a; 无论分片数量多少&#xff0c;它总…

【人工智能大脑】仿生学与人工智能交汇:基于MP神经网络的精准农业实践

MP神经网络&#xff0c;即McCulloch-Pitts模型&#xff08;MCP Model&#xff09;&#xff0c;是神经网络的早期形式之一&#xff0c;由Warren McCulloch和Walter Pitts在1943年提出。这个模型为现代人工神经网络的发展奠定了理论基础&#xff0c;并首次尝试模拟了生物神经元的…

Kotlin程序设计 扩展篇(一)

Kotlin程序设计&#xff08;扩展一&#xff09; **注意&#xff1a;**开启本视频学习前&#xff0c;需要先完成以下内容的学习&#xff1a; 请先完成《Kotlin程序设计》视频教程。请先完成《JavaSE》视频教程。 Kotlin在设计时考虑到了与Java的互操作性&#xff0c;现有的Ja…

RK3568 移植Ubuntu

使用ubuntu-base构建根文件系统 1、到ubuntu官网获取 ubuntu-base-18.04.5-base-arm64.tar.gz Ubuntu Base 18.04.5 LTS (Bionic Beaver) 2、将获取的文件拷贝到ubuntu虚拟机,新建目录,并解压 mkdir ubuntu_rootfs sudo tar -xpf u

Ubuntu之离线安装Gitlab,搭建私有代码仓库

Ubuntu之离线安装Gitlab,搭建私有代码仓库 文章目录 Ubuntu之离线安装Gitlab,搭建私有代码仓库1. 官网下载&#xff1a;2. 安装Gitlab3. 使用 1. 官网下载&#xff1a; https://packages.gitlab.com/gitlab/gitlab-ce wget下载地址&#xff1a; wget https://packages.gitla…

Linux命令_vim的详细用法

简介 vim是一款针对Linux和其他类Unix操作系统的文本编辑器。它是Vi编辑器的升级版本&#xff0c;具有丰富的功能和强大的扩展性。vim有三种基本模式&#xff1a;命令模式、插入模式和可视模式。 命令模式&#xff1a;用户可以使用各种命令移动光标和进行编辑操作&#xff0c;如…

安裝火狐和穀歌流覽器插件FoxyProxy管理海外動態IP代理

代理生態系統擁有大量有用的實用程式&#xff0c;使海外代理IP代理設置的使用變得簡單起來。其中一種類型叫做代理管理工具&#xff0c;像FoxyProxy就是該工具集比較受歡迎的。 本文將全面解析FoxyProxy擴展的功能和特性、Foxyproxy怎麼下載、以及如何在穀歌流覽器和火狐流覽器…

数据分析的理念、流程、方法、工具(上)

一、数据的价值 1、数据驱动企业运营 从电商平台的「猜你喜欢」到音乐平台的「心动模式」&#xff0c;大数据已经渗透到了我们生活的每一个场景。不论是互联网行业&#xff0c;还是零售业、制造业等&#xff0c;各行各业都在依托互联网大数据&#xff08;数据采集、数据存储、…

AutoDL——终端训练神经网络模型(忽略本地问题)

前言&#xff1a; 本人之前分享过一篇文章&#xff1a;使用pycharm连接远程GPU训练神经网络模型&#xff08;超详细&#xff01;&#xff09;&#xff0c;其中详细介绍了如何利用pycharm连接AutoDL算力云平台租用的GPU服务器训练网络模型。但有些小伙伴可能会因为一些原因而导…