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

回调函数的实现

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

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

代码示例:

cpp 复制代码
#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主:码农论坛,该文章仅作为本人学习笔记及交流学习使用。

相关推荐
别NULL1 分钟前
机试题——最小矩阵宽度
c++·算法·矩阵
珊瑚里的鱼2 分钟前
【单链表算法实战】解锁数据结构核心谜题——环形链表
数据结构·学习·程序人生·算法·leetcode·链表·visual studio
林涧泣3 分钟前
图的矩阵表示
学习·线性代数·矩阵
chimchim6610 分钟前
【starrocks学习】之catalog
学习
stevewongbuaa33 分钟前
一些烦人的go设置 goland
开发语言·后端·golang
撸码到无法自拔1 小时前
MATLAB中处理大数据的技巧与方法
大数据·开发语言·matlab
Icomi_1 小时前
【外文原版书阅读】《机器学习前置知识》1.线性代数的重要性,初识向量以及向量加法
c语言·c++·人工智能·深度学习·神经网络·机器学习·计算机视觉
apocelipes1 小时前
Linux glibc自带哈希表的用例及性能测试
c语言·c++·哈希表·linux编程
Jackilina_Stone1 小时前
【论文阅读笔记】“万字”关于深度学习的图像和视频阴影检测、去除和生成的综述笔记 | 2024.9.3
论文阅读·人工智能·笔记·深度学习·ai
梦云澜1 小时前
论文阅读(二):理解概率图模型的两个要点:关于推理和学习的知识
论文阅读·深度学习·学习