当前位置: 首页 > news >正文

C++ 包装器与绑定器的应用之回调函数的实现

回调函数的实现

在消息队列和网络库的框架中,当接收到消息(报文)时,回调用户自定义的函数对象,把消息(报文)参数传给它,由它决定如何处理。

queue参考文章:C++ queue(STL queue,队列)用法详解_queue c++ 用法-CSDN博客

代码示例:

#include <iostream>#include <string>#include <thread>                      // 线程类头文件。#include <mutex>                      // 互斥锁类的头文件。#include <deque>                      // deque容器的头文件。#include <queue>                      // queue容器的头文件。#include <condition_variable>  // 条件变量的头文件。#include <functional>using namespace std;void show(const string& message) {  // 处理业务的普通函数cout << "处理数据:" << message << endl;}struct BB {  // 处理业务的类void show(const string& message) {cout << "处理表白数据:" << message << endl;}};class AA{mutex m_mutex;                                    // 互斥锁。condition_variable m_cond;                  // 条件变量。queue<string, deque<string>> m_q;   // 缓存队列,底层容器用deque。function<void(const string&)> m_callback;  // 回调函数对象。public:// 注册回调函数,回调函数只有一个参数(消费者接收到的数据)。template<typename Fn, typename ...Args>void callback(Fn && fn, Args&&...args) {m_callback = bind(forward<Fn>(fn), forward<Args>(args)..., std::placeholders::_1);  // 绑定回调函数。}void incache(int num)     // 生产数据,num指定数据的个数。{lock_guard<mutex> lock(m_mutex);   // 申请加锁。for (int ii = 0; ii < num; ii++){static int bh = 1;           // 编号。string message = to_string(bh++) + "号";    // 拼接出一个数据。m_q.push(message);     // 把生产出来的数据入队。}//m_cond.notify_one();     // 唤醒一个被当前条件变量阻塞的线程。m_cond.notify_all();          // 唤醒全部被当前条件变量阻塞的线程。}void outcache() {    // 消费者线程任务函数。while (true) {// 把互斥锁转换成unique_lock<mutex>,并申请加锁。unique_lock<mutex> lock(m_mutex);// 1)把互斥锁解开;2)阻塞,等待被唤醒;3)给互斥锁加锁。m_cond.wait(lock, [this] { return !m_q.empty(); });// 数据元素出队。string message = m_q.front();  m_q.pop();cout << "线程:" << this_thread::get_id() << "," << message << endl;lock.unlock();      // 手工解锁。// 处理出队的数据(把数据消费掉)。if (m_callback) m_callback(message);  // 回调函数,把收到的数据传给它。}}};int main(){AA aa;// aa.callback(show);                   // 把普通函数show()注册为回调函数。BB bb;aa.callback(&BB::show, &bb);    // 把类成员函数BB::show()注册为回调函数。thread t1(&AA::outcache, &aa);     // 创建消费者线程t1。thread t2(&AA::outcache, &aa);     // 创建消费者线程t2。thread t3(&AA::outcache, &aa);     // 创建消费者线程t3。this_thread::sleep_for(chrono::seconds(2));    // 休眠2秒。aa.incache(2);      // 生产2个数据。this_thread::sleep_for(chrono::seconds(3));    // 休眠3秒。aa.incache(5);      // 生产5个数据。t1.join();   // 回收子线程的资源。t2.join();t3.join();}

注:此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记及交流学习使用。   

http://www.lryc.cn/news/526659.html

相关文章:

  • Baichuan大模型Base、Chat、Instruct等版本的区别
  • 3.DrawCall的概念
  • ubuntu电脑调用摄像头拍摄照片
  • PyQt4 的图片切割编辑器
  • mac 电脑上安装adb命令
  • Webrtc (1) - Windows 编译
  • 学习数据结构(1)算法复杂度
  • GCC之编译(8)AR打包命令
  • RocketMQ原理—4.消息读写的性能优化
  • (Halcon)轮廓等分切割(项目分析)
  • NIO 和 Netty 在 Spring Boot 中的集成与使用
  • 【更正版】梯级水光互补系统最大化可消纳电量期望短期优化调度模型
  • 基于AnolisOS 8.6安装GmSSL 3.1.1及easy_gmssl库测试国密算法
  • vue3 实际应用 将一个日期使用 moment.js 实现星期 今天 明天 ...
  • LLM幻觉(Hallucination)缓解技术综述与展望
  • Unity入门2 背景叠层 瓦片规则
  • docker-制作镜像gcc添加jdk运行java程序
  • HashTable, HashMap, ConcurrentHashMap 之间的区别
  • vue2和vue3组件之间的通信方式差异
  • 报错:MC1000未知的生成错误Invalid number of sections declared in PE header
  • FPGA实现任意角度视频旋转(二)视频90度/270度无裁剪旋转
  • Linux(Centos 7.6)命令详解:wc
  • centos7执行yum操作时报错Could not retrieve mirrorlist http://mirrorlist.centos.org解决
  • C语言程序设计:算法程序的灵魂
  • openlayer getLayerById 根据id获取layer图层
  • 在 vscode + cmake + GNU 工具链的基础上配置 JLINK
  • react antd点击table单元格文字下载指定的excel路径
  • 01-AD工具使用
  • centos7 配置国内镜像源安装 docker
  • Java设计模式 十八 状态模式 (State Pattern)