线程库接口模拟封装(使用参数包接受参数,2种方法)

news2025/3/14 4:07:06

目录

引入

模拟实现

思路

传递参数包

代码

thread.hpp

main.cpp

示例


引入

之前我们一直使用的都是linux中的原生线程库,但c++中其实是有提供封装好的线程库的 -- <thread>

下面我们也来试着封装一下线程接口

模拟实现

思路

首先,明确线程库的核心操作:

  • 创建和销毁线程

其次,明确需要的信息(变量):

  • 线程id
  • 线程执行函数

这里,我们贴近标准库中的定义,使用参数包接收传入的参数

  • 所以我们还需要定义一个tuple类型(元组),来存放参数包
  • 因为参数包类型之间不能直接赋值,所以我们需要使用元组作为中间媒介

和标准线程库相比,我们还可以添加一些额外信息:

  • 线程名
  • 线程创建时间

传递参数包

基本难点都在于 -- 如何将接收到的参数包,传递给传入的函数方法

我们这里提供两种解决方法:

  • 使用c++14提供的索引序列模板类(index_sequence)作为辅助,然后使用get函数展开参数包
  • 使用c++17提供的apply函数,它可以直接将参数包的元素传递给函数

代码

thread.hpp

#include <pthread.h>
#include <stdlib.h>
#include <string>
#include <unistd.h>
#include <functional>
#include <iostream>

template <typename... Args>
using callback_t = std::function<void(Args...)>; // 定义一个函数类型,用于接收传入的函数指针

static int NUM = 1;

template <class... Args>
class thread
{
public:
    thread(callback_t<Args...> cb, Args... args)
        : tid_(0), name_(""), start_timestamp_(0), args_(std::make_tuple(args...)), callback_(cb) // 将参数包展开,创建一个元组
    {
        std::string name = "pthread" + std::to_string(NUM++);
        name_ = name;
        start_timestamp_ = time(nullptr);

        pthread_create(&tid_, nullptr, entry, this);
    }
    ~thread()
    {
    }
    void join()
    {
        pthread_join(tid_, nullptr);
    }
    std::string get_name()
    {
        return name_;
    }
    uint64_t get_time()
    {
        return start_timestamp_;
    }
    pthread_t get_id()
    {
        return tid_;
    }

private:
    // 使用索引序列传递
    static void *entry(void *args) // 调用存放的函数方法
    {
        thread *it = static_cast<thread *>(args);
        it->call(std::index_sequence_for<Args...>()); // 根据参数包生成索引序列
        return nullptr;
    }
    template <std::size_t... Is>
    void call(std::index_sequence<Is...>)
    {
        callback_(std::get<Is>(args_)...); // 将元组中的参数按照索引序列,逐个传递给callback_
    }

    // 使用折叠表达式直接展开
    static void *entry(void *args)
    {
        thread *it = static_cast<thread *>(args);
        std::apply(it->callback_, it->args_);
        return nullptr;
    }

private:
    pthread_t tid_;
    callback_t<Args...> callback_; // 存储函数方法
    std::tuple<Args...> args_;     // 存储参数包

    std::string name_;
    uint64_t start_timestamp_;
};

main.cpp

#include "thread.hpp"
#include <time.h>

using namespace std;

void test1(int x)
{
    cout << x << endl;
    usleep(20);
}
void test2(string data, int id)
{
    usleep(20);
    cout << id << ":data is " << data << endl;
    usleep(20);
}
int main()
{
    thread<int> t1(test1, 100);
    thread<string, int> t2(test2, "hello world", 2);
    t1.join();
    t2.join();
    cout << t1.get_name() << endl;
    cout << t2.get_name() << ":" << t2.get_time() << endl;
    return 0;
}

示例

可以看到,我们成功创建出线程,且正确执行了派发的函数任务:

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

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

相关文章

标签结构比目录结构更易用 | Obsidian实践

当我顿悟了标签结构&#xff08;标签树&#xff09;的构建逻辑&#xff0c;彻底摆脱了目录结构的限制&#xff0c;从此可按任意维度管理和检索笔记。 对于每一个新入坑Obsidian的小白菜来说&#xff0c;通过创建目录结构&#xff0c;对笔记进行管理是最符合直觉的方式。但是&am…

【AIGC】大语言模型

大型语言模型&#xff0c;也叫大语言模型、大模型&#xff08;Large Language Model&#xff0c;LLM&#xff1b;Large Language Models&#xff0c;LLMs&#xff09; 什么是大型语言模型 大型语言模型&#xff08;LLM&#xff09;是指具有数千亿&#xff08;甚至更多&#xf…

php switch、for、foreach、while、do...while

php switch 1. switch2. for循环3. foreach4. while、do...while 1. switch <?php$height 190;switch ($height) {case 160:echo 太矮了;break; //跳出本次循环case 170:echo 还行吧;break; //跳出本次循环case 180:echo 帅哥;break; //跳出本次循环default:echo 迷; }2.…

初始Git及Linux Centos下安装Git

文章目录 前言版本控制器注意Git安装 前言 不知道你⼯作或学习时&#xff0c;有没有遇到这样的情况&#xff1a;我们在编写各种⽂档时&#xff0c;为了防⽌⽂档丢失&#xff0c;更改失误&#xff0c;失误后能恢复到原来的版本&#xff0c;不得不复制出⼀个副本&#xff0c;⽐如…

springboot196高校教师科研管理系统

Spring Boot高校教师科研管理系统设计与实现 摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜…

(八)【Jmeter】线程(Threads(Users))之bzm - Concurrency Thread Group

简述 操作路径如下: 作用:模拟一定时间段内达到指定并发数的用户访问。配置:设置目标并发数、启动时间、持续时间等参数。使用场景:测试应用程序在达到一定并发用户数时的性能表现。优点:能够模拟实际并发访问的增长和稳定过程。缺点:主要关注并发数,可能无法模拟真实…

C高级D5作业

1.#!/bin/bash read -p "请输入一个字符>>" -n 1 c echo case $c in [[:lower:]]) echo "小写" ;; [[:upper:]]) echo "大写" ;; [1-9]) echo "数字" ;; …

如何实现Vuex数据持久化

Vuex是一个非常流行的状态管理工具&#xff0c;它可以帮助我们在Vue.js应用中管理和共享数据。然而&#xff0c;当应用重新加载或刷新时&#xff0c;Vuex的状态会被重置&#xff0c;这就导致了数据的丢失。那么&#xff0c;如何才能实现Vuex的数据持久化呢&#xff1f;让我们一…

【自然语言处理】seq2seq模型—机器翻译

清华大学驭风计划课程链接 学堂在线 - 精品在线课程学习平台 (xuetangx.com) 代码和报告均为本人自己实现&#xff08;实验满分&#xff09;&#xff0c;只展示主要任务实验结果&#xff0c;如果需要详细的实验报告或者代码可以私聊博主 有任何疑问或者问题&#xff0c;也欢…

SECS/GEM的HSMS通讯?金南瓜方案

High Speed SECS Message Service (HSMS) 是一种基于 TCP/IP 的协议&#xff0c;它使得 SECS 消息通信更加快速。这通常用作设备间通信的接口。 HSMS 状态逻辑变化&#xff08;序列&#xff09;&#xff1a; 1.Not Connected&#xff1a;准备初始化 TCP/IP 连接&#xff0c;但尚…

使用Autodl云服务器或其他远程机实现在本地部署知识图谱数据库Neo4j

本篇博客的目的在于提高读者的使用效率 温馨提醒&#xff1a;以下操作均可在无卡开机状态下就可完成 一.安装JDK 和 Neo4j 1.1 ssh至云服务器 打开你的pycharm或者其他IDE工具或者本地终端&#xff0c;ssh连接到autodl的服务器。(这一步很简单如下图) 1.2 安装JDK 由于我…

入门OpenCV:图像阈值处理

基本概念 图像阈值是一种简单、高效的图像分割方法&#xff0c;目的是将图像转换成二值图像。这个过程涉及比较像素值和阈值&#xff0c;根据比较结果来确定每个像素点的状态&#xff08;前景或背景&#xff09;。图像阈值在处理二维码、文本识别、物体跟踪等领域中非常有用。…

PLC_博图系列☞LAD

PLC_博图系列☞LAD 文章目录 PLC_博图系列☞LAD背景介绍LAD优势局限 LAD元素 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 LAD 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的博图软件。我并不是专业的PLC编程人员&#xff0c;也不懂电路&a…

[0]是数字的最右边

像这一段代码&#xff0c;把控制信号Ctrl的值&#xff0c;根据此时计数器的值&#xff0c;从Ctrl[0]到Ctrl[7]赋值给led。 之前的理解错误 之前脑子昏头了&#xff0c;看下面的这个图一直觉得不对&#xff0c;才发现这个Ctrl的值我应该从最右边读&#xff0c;即控制信号为Ctrl…

【项目实现】自主HTTP服务器

自主HTTP服务器 项目介绍网络协议栈介绍协议分层 数据的封装与分用数据的封装与分用 HTTP相关知识介绍HTTP的特点 URL格式URI、URL、URNHTTP的协议格式HTTP的请求方法HTTP的状态码HTTP常见的Header CGI机制介绍CGI机制的概念CGI机制的实现步骤CGI机制的意义 日志编写套接字相关…

萨科微半导体宋仕强介绍说

萨科微半导体宋仕强介绍说&#xff0c;电源管理芯片是指在电子设备系统中&#xff0c;负责对电能的变换、分配、检测等进行管理的芯片&#xff0c;其性能和可靠性直接影响电子设备的工作效率和使用寿命&#xff0c;是电子设备中的关键器件。萨科微slkor&#xff08;www.slkormi…

智慧城管建设方案

第5章智慧城管可视化平台 5.1 视频综合管理平台 5.1.1 平台架构 整个视频监控管理平台在架构上分为五个层次&#xff0c;底层是基础硬件支撑层和基础软件支撑层&#xff0c;是支持整个系统运行必要的系统硬件和环境&#xff0c;网络基础设施包括了电子政务网、视频监控专网、…

vue3之setup的基本使用

setup是一个全新的配置项&#xff0c;值是一个函数&#xff0c;既然是配置项&#xff0c;是否与data、methods是兄弟&#xff1f; 没错&#xff0c;确实是兄弟关系&#xff0c;只不过到了vue3&#xff0c;就不怎么使用data这些配置项&#xff0c;会使用setup&#xff0c;让我为…

文件上传漏洞--Upload-labs--Pass02--Content-Type绕过

一、什么是 Content-Type 我们在上传文件时利用 Burpsuite 进行抓包&#xff0c;如下图所示&#xff1a; 上传文件后台的源代码可能会对 Content-Type 进行规定&#xff0c;设置白名单 或 黑名单&#xff0c;这时就要利用Content-Type绕过上传含有恶意代码的 php文件。 二、代…

链表总结 -- 《数据结构》-- c/c++

链表的概念 链表是一种物理存储结构上非连续存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的引用链接次序实现的 。 链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个节点的…