c++ 实现线程池、实现异步接口

c++ 实现线程池,下面给出测试用例

mian.cpp

#include <iostream>
#include <thread>
#include <chrono>#include "threadpool.h"
#include "callback_proxy.h"using namespace std;
using namespace Demo;bool GetTimeImpl(int& time) {std::cout << std::endl;std::cout << std::this_thread::get_id() <<": 开始延时..." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(5));std::cout << std::this_thread::get_id() <<": 延时结束..." << std::endl;time = 5201314;return true;
}typedef void(*msg_func)(int time, const void* user_data);
bool GetTimeImplAsync(msg_func callback, const void* user_data)
{int  time = -1;bool result = GetTimeImpl(time);if (callback) {callback(time, user_data);  // 触发回调}return result;
}typedef std::function<void(int)> FunCallback;
static void CallbackNotify(int time, const void* callback)
{CallbackProxy::DoSafeCallback<FunCallback>(callback, [=](const FunCallback& cb){CallbackProxy::Invoke(cb, time);});
}// 异步获取时间
bool GetTimeAsync(const FunCallback& callback)
{FunCallback* callback_impl = nullptr;if (callback) {callback_impl = new FunCallback(callback);}Threadpool* thread_pool = Threadpool::GetInstance();if (thread_pool != nullptr) {thread_pool->Commit(GetTimeImplAsync, &CallbackNotify, callback_impl);return true;}false;
}// 同步获取时间
bool GetTime(int &time)
{bool result = GetTimeImpl(time);return result;
}int main() {std::cout << "main start" << std::endl;int time;GetTime(time); // 同步获取时间std::cout << "tongbu time:" <<time << std::endl;std::cout << "*********" << std::endl;GetTimeAsync([](int time) {  // 异步获取时间std::cout << "yibu time:" << time << std::endl;});std::cout << "main end" << std::endl << std::endl;getchar();return 0;
}

threadpool.h

/*************************************************
** Copyright:   xxx公司
** Author:      xxx
** Date:        xxx
** Description: 线程池
**************************************************/
#ifndef THREADPOOL_H_
#define THREADPOOL_H_#include <vector>
#include <queue>
#include <thread>
#include <atomic>
#include <condition_variable>
#include <future>
#include <functional>
#include <stdexcept>class Threadpool {
public:Threadpool(int size = 4) {stopped_ = false;idl_thread_number_ = 0;idl_thread_number_ = size < 1 ? 1 : size;for (int i = 0; i < idl_thread_number_; ++i) {   //初始化线程数量pool_.emplace_back(std::thread(&Threadpool::Run, this));}}~Threadpool() {// 线程退出,释放资源stopped_.store(true);cv_task_.notify_all(); // 唤醒所有线程执行for (auto& item : pool_) {if (item.joinable())item.join();}}static Threadpool* GetInstance() {static Threadpool threadpool;return &threadpool;}public:// 提交任务加入队列// 可调用.get()等待任务执行完,获取返回值template<class F, class... Args>auto Commit(F&& f, Args&&... args)->std::future<decltype(f(args...))>{using RetType = decltype(f(args...));auto task = std::make_shared<std::packaged_task<RetType()> >(std::bind(std::forward<F>(f), std::forward<Args>(args)...));std::future<RetType> future = task->get_future();if (stopped_.load()) return future;{// 添加任务到队列std::lock_guard<std::mutex> lock(lock_);tasks_.emplace([task](){(*task)();});}cv_task_.notify_one(); // 唤醒一个线程执行return future;}// 空闲线程数量inline int idl_thread_number() { return idl_thread_number_; }protected:void Run() {while (!this->stopped_) {std::function<void()> task;{std::unique_lock<std::mutex> lock{ this->lock_ };this->cv_task_.wait(lock,[this] {return this->stopped_.load() || !this->tasks_.empty();}); // wait 直到有 taskif (this->stopped_ && this->tasks_.empty())return;task = std::move(this->tasks_.front());this->tasks_.pop();}idl_thread_number_--;task();idl_thread_number_++;}}private:using Task = std::function<void()>;std::vector<std::thread> pool_;                  // 线程池std::queue<Task>         tasks_;                 // 任务队列std::mutex               lock_;                  // 同步std::condition_variable  cv_task_;               // 条件阻塞std::atomic<bool>        stopped_;               // 是否关闭提交std::atomic<int>         idl_thread_number_;     // 空闲线程数量
};#endif // THREADPOOL_H_

callback_proxy.h

/*************************************************
** Copyright:   xxx信息
** Author:      xxx
** Date:        xxx
** Description: xxx
**************************************************/
#ifndef CALLBACK_PROXY_H_
#define CALLBACK_PROXY_H_#include <functional>
#include <memory>namespace Demo
{
class CallbackProxy
{template<typename TR = void>using CallbackProxyClosure = std::function<TR(void)>;public:template<typename TCallback, typename TDoCall>static auto DoSafeCallback(const void* callback, const TDoCall& closure, bool delete_callback = false)->decltype(closure((*(TCallback*)(callback)))){using TCallbackPtr = TCallback*;using TReturn = decltype(closure((*(TCallbackPtr)(callback))));struct Deleter {Deleter(TCallbackPtr cb_ptr) : cb_ptr_(cb_ptr) {}~Deleter() {if (cb_ptr_ != nullptr) {delete cb_ptr_;cb_ptr_ = nullptr;}}private: TCallbackPtr cb_ptr_;};if (callback != nullptr) {auto&& real_type_cb_ptr = (TCallbackPtr)(callback);Deleter deleter(delete_callback ? real_type_cb_ptr : nullptr);return (*real_type_cb_ptr == nullptr) ? (TReturn()) : (closure(std::forward<TCallback>(*real_type_cb_ptr)));}return TReturn();}template<class F, class... Args, class = typename std::enable_if<!std::is_member_function_pointer<F>::value>::type>static auto Invoke(F && f, Args && ... args)->decltype(f(std::forward<Args>(args)...)){using TReturn = decltype(f(std::forward<Args>(args)...));return Run<TReturn>(std::bind(f, std::forward<Args>(args)...));}template<class R, class C, class... DArgs, class P, class... Args>static R Invoke(R(C::*f)(DArgs...) const, P && p, Args && ... args){using TReturn = R;return Run<TReturn>(std::bind(f, p, std::forward<Args>(args)...));}template<class R, class C, class... DArgs, class P, class... Args>static R Invoke(R(C::*f)(DArgs...), P && p, Args && ... args){using TReturn = R;return Run<TReturn>(std::bind(f, p, std::forward<Args>(args)...));}protected:template<typename TR>static TR Run(const CallbackProxyClosure<TR>& task){return task();}//template<>static void Run(const CallbackProxyClosure<void>& task){if (docallback_async_ != nullptr) {docallback_async_(task);} else {task();}}private:static std::function<void(const std::function< void()>&)> docallback_async_;
};
}#endif  // CALLBACK_PROXY_H_

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

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

相关文章

目标检测——车牌数据集

一、重要性及意义 交通安全与管理&#xff1a;车牌检测和识别技术有助于交通管理部门快速、准确地获取车辆信息&#xff0c;从而更有效地进行交通监控和执法。例如&#xff0c;在违规停车、超速行驶等交通违法行为中&#xff0c;该技术可以帮助交警迅速锁定违规车辆&#xff0…

零日攻击

简介 零日攻击&#xff0c;原名Zero-Day Attack&#xff0c;是指利用软件或系统中未被发现的安全漏洞进行的攻击。攻击者利用这些漏洞来执行恶意代码、窃取数据或控制系统&#xff0c;而系统开发者还未发布相应的补丁或安全更新来修复这些漏洞。 类型 利用已知漏洞的零日攻击…

docker安装jenkins 2024版

docker 指令安装安装 docker run -d --restartalways \ --name jenkins -uroot -p 10340:8080 \ -p 10341:50000 \ -v /home/docker/jenkins:/var/jenkins_home \ -v /var/run/docker.sock:/var/run/docker.sock \ -v /usr/bin/docker:/usr/bin/docker jenkins/jenkins:lts访问…

简述vue3新特性

Vue 3 带来了许多新特性和改进&#xff0c;其中最重要的是 Composition API。但除了这个&#xff0c;Vue 3 还在模板语法、指令、组件等方面有所更新。以下是对 Vue 3 语法的详细说明&#xff1a; Composition API Vue 3 引入了 Composition API&#xff0c;这是一种新的、可…

es创建索引(mapping和setting)

1、首先定义一个索引&#xff0c;如下 PUT /person_news {"settings": {"index": {"number_of_shards": "3","number_of_replicas": "0","max_result_window": "2000000000"}},"mappin…

c 储存类

文章目录 概要整体架构流程 概要 存储类定义 C 程序中变量/函数的存储位置、生命周期和作用域。 这些说明符放置在它们所修饰的类型之前。 下面列出 C 程序中可用的存储类&#xff1a; autoregisterstaticextern 整体架构流程 auto 存储类 auto 存储类是所有局部变量默认的…

AD方法概述应用

1. 背景 异常(异常值、离群点)一般指的是与标准值或期待值有偏离的样本&#xff0c;即与绝大部分数据“长得不一样”。 2. 异常检测(Anomaly Detection) 2.1 AD的一些特点 1. 异常不一定代表是“坏”的事情&#xff0c;但往往是“有价值”的事情&#xff0c;要对异常的成因感…

数据结构(无图版)

数据结构与算法&#xff08;无图版&#xff0c;C语言实现&#xff09; 1、绪论 1.1、数据结构的研究内容 一般应用步骤&#xff1a;分析问题&#xff0c;提取操作对象&#xff0c;分析操作对象之间的关系&#xff0c;建立数学模型。 1.2、基本概念和术语 数据&#xff1a;…

贝锐蒲公英企业路由器双机热备,保障异地组网可靠、不中断

对于关键业务&#xff0c;比如&#xff1a;在线支付系统、远程医疗监控系统、重要数据中心等&#xff0c;一旦网络发生故障&#xff0c;可能导致巨大的损失或影响&#xff0c;因此需确保网络拥有极高的可靠性、稳定性和容错能力。 面对此类场景和需求&#xff0c;贝锐蒲公英异…

【数据结构与算法】归并排序(详解:递归与非递归的归并排序 | 赠:冒泡排序和选择排序)

前言 本篇博客会对排序做一个收尾&#xff0c;将最经典的七大排序介绍完毕。 这次的重点正如标题&#xff0c;主要讲的是归并排序&#xff0c;还会带过相对简单很多的冒泡排序和选择排序。在最后还会给这七大排序做出一个时间复杂度和稳定性展示的总结收尾。同时&#xff0c;这…

(4)(4.6) Triducer

文章目录 前言 1 安装triducer 2 故障排除 3 参数说明 前言 Triducer 集速度、温度和深度传感器于一体。埃文在这篇 ardupilot.org 博文底部提供了这些说明(Evan at the bottom of this ardupilot.org blog post)。 1 安装triducer 下面的示例提供了在 Pixhawk 上安装 tri…

抽象类与抽象方法(或abstract关键字)练习题

练习一 编写工资系统&#xff0c;实现不同类型员工(多态)的按月发放工资。如果当月出现某个Employee对象的生日&#xff0c;则将该雇员的工资增加100元。实验说明&#xff1a;&#xff08;1&#xff09;定义一个Employee类&#xff0c;该类包含&#xff1a;private成员变量na…

NOSQL(非关系型数据库)的优缺点有哪些?

优点&#xff1a; 高度灵活且可扩展&#xff1a;NoSQL数据库不受固定数据模型的限制&#xff0c;可以根据应用需求灵活设计数据结构&#xff0c;轻松应对大规模数据集。此外&#xff0c;它支持分布式架构&#xff0c;具有出色的水平扩展能力&#xff0c;能够高效地处理大量数据…

C语言中的数组与函数指针:深入解析与应用

文章目录 一、引言二、数组的定义1、数组的定义与初始化2、char*与char[]的区别1. 存储与表示2. 修改内容3. 作为函数参数 三、字符串指针数组1. 定义与概念2. 使用示例3. 内存管理 四、从字符串指针数组到函数指针的过渡1、字符串指针数组的应用场景2、函数指针的基本概念3、如…

【管理咨询宝藏48】AA银行信息科技提升分析报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏48】AA银行信息科技提升分析报告 【格式】PPT版本&#xff0c;可编辑 【关键词】战略规划、商业分析、管理咨询 【强烈推荐】这是一套市面上非常…

Vue 中的修饰符

Vue 中的修饰符是一种特殊的后缀&#xff0c;用于改变指令的行为。它们主要可以分为以下几种类型&#xff1a; 事件修饰符&#xff1a;用于监听 DOM 事件时的修饰符。常见的事件修饰符包括 .stop&#xff08;阻止事件继续传播&#xff09;、.prevent&#xff08;阻止事件的默认…

【代码篇】事件监听函数的内存泄漏,都给我退散吧!

前言 内存泄漏是个很严肃的问题&#xff0c;可是迄今也没有一个非常有效的排查方案&#xff0c;本方案就是针对性的单点突破。 工作中&#xff0c;我们会对window, DOM节点&#xff0c;WebSoket, 或者单纯的事件中心等注册事件监听函数, 添加了&#xff0c;没有移除&#xff…

count(“0“),split() ,sys.stdin.readline() ,matrix.append, input().strip()

目录 count() 方法主要用于计算一个序列(例如列表、元组或字符串)中某个元素出现的次数

开源软件技术社区方案

开源软件技术社区是一个由开发者、贡献者、用户和维护者组成的共享平台&#xff0c;主要目的是打造技术、软件产品良性互动、开源技术安全可控的软件生态环境&#xff0c;实现可复用应用或服务的快速部署与使用、完成资源与能力的高度共享、促进社区成员的共建共赢&#xff0c;…

提高机器人系统稳定性:引入阻尼作为共振后的相位超前

在机器人关节中&#xff0c;引入阻尼作为共振后的相位超前&#xff0c;确实是一种提高系统稳定性的有效策略。机器人关节的振动和共振是影响其性能稳定性的关键因素&#xff0c;特别是在进行高速、高精度操作时。阻尼的引入能够显著减少这些不利因素&#xff0c;提升机器人的整…