业务类处理自定义消息

#include <iostream>
#include <thread>
#include <stdlib.h>
#include <unistd.h>
#include <queue>
#include <assert.h>
#include <mutex>
#include <condition_variable>
using namespace std;

///TMsgQue是模板类,可以实例化成各种消息
template<typename M>
class TMsgQue
{
public:
    ///创建消息队列
    TMsgQue(int queueSize = 1024)
    {
        m_queueSize = queueSize;
    };

    virtual ~TMsgQue(){};

    ///sendMessage函数是存储消息的函数
    ///消息的存储和获取通过锁和条件变量来控制
    ///当消息队列为空并且wait为true时recvMessage是被条件变量阻塞的
    ///当消息队列为空并且wati为false是,recvMessage不会被阻塞
    ///当sendMessage的时候消息队列不为空条件变量唤醒阻塞的recvMessage函数
    bool sendMessage (M& message)
    {
        unique_lock<mutex> locker(m_mutex);//锁
        if(m_queue.size() >= (size_t)m_queueSize)
        {
            return false;
        }

        m_queue.push(message);
        cond.notify_one();

        return true;
    };

    ///recvMessage是获取消息的函数
    ///如果消息队列为空并且wait为true,则该函数是被条件变量阻塞
    ///如果消息队列为空并且wait为false,则该函数返回false
    ///如果消息队列不为空,recvMessage会被唤醒
    bool recvMessage (M& message, bool wait = true)
    {
        unique_lock<mutex> lock(m_mutex);

        if (!wait)
        {
            if (m_queue.empty())
            {
                return false;
            }
        }

        if (m_queue.empty())
        {
            cond.wait(lock); 
        }

        message = m_queue.front();
        m_queue.pop();

        return true;
    }

    void clean()
    {
        std::unique_lock<std::mutex>lock(m_mutex);

        int n = m_queue.size();
        for(int i = 0; i < n; i++)
        {
            cond.wait(lock);
            m_queue.pop_back();
        }
    }

    /// 得到消息队列中消息个数
    int size()
    {
        std::unique_lock<std::mutex>lock(m_mutex);

        return m_queue.size();
    }

    /// 得到消息队列的最大长度
    int getMaxSize()
    {
        std::unique_lock<std::mutex>lock(m_mutex);

        return m_queueSize;
    }

    /// 得到消息队列的最大长度,将在下次SendMessage时生效
    /// \param size 新的消息队列长度,可以比原来的大或者小
    void setMaxSize(int size)
    {
        std::unique_lock<std::mutex>lock(m_mutex);

        m_queueSize = size;
    }
private:
    typedef std::queue<M> Queue;
    Queue m_queue;
    std::mutex m_mutex;
    condition_variable cond;
    int m_queueSize;
};

///事件枚举
typedef enum Event
{
    init = 1,
    first = 2,
    second = 3,
    four = 4,
}Event;

///消息结构体
typedef struct Message
{
    Event event;
    std::string str;
    int num;
    ///这里可以自定义数据类型,比如json,结构体等
}Message;

///生产者和消费者模式
///main函数是主线程,是生产者, Fun类的f函数是子线程,是消费者
///主线程通过消息队列给子线程发送消息,如果有消息,子线程就处理消息,否则子线程被条件变量阻塞,等待消息
class Fun
{
public:
    void start()
    {
        m_bFlag = true;
    }

    void stop()
    {
        printf("Fun thread over..\n");
        m_bFlag = false;
    }

    void f()
    {
        while(m_bFlag)
        {
            sleep(1);
            Message m;
            ///消息统一出口函数,不会漏掉消息
            ///线程根据事件类型处理不同的消息
            ///当recvMessage的第二个参数是true并且没有收到消息, 线程就被条件变量阻塞住,不会往下执行,如果收到消息则ret=1就可以处理消息
            ///当recvMessage的第二个参数是false并且没有消息处理,ret=0,线程空转
            ///当recvMessage的第二个参数是false并且有消息,ret=1,线程处理消息
            int ret = m_Message.recvMessage(m);
            ///int ret = m_Message.recvMessage(m, false);
            if (ret)
            {
                if (m.event == init)
                {
                    cout << "event:" << m.event << "\tstr:" << m.str << "\tnum:" << m.num << endl;
                }
                else if (m.event == first)
                {
                    cout << "event:" << m.event << "\tstr:" << m.str << "\tnum:" << m.num << endl;
                }
                else if (m.event == second)
                {
                    cout << "event:" << m.event << "\tstr:" << m.str << "\tnum:" << m.num << endl;

                    ///在线程中也可以发送消息
                    Message m;
                    m.event = four;
                    m.str = "chanhui";
                    m.num = 1234;
                    m_Message.sendMessage(m);
                }
                else if (m.event == four)
                {
                    cout << "event:" << m.event << "\tstr:" << m.str << "\tnum:" << m.num << endl;
                }
            }
            printf("m_Message after size:%d\n", m_Message.size());
        }
    }

    ///消息统一入口函数,不会漏掉消息
    void sendMessage(Event event, std::string str, int num)
    {
        printf("m_Message before size:%d\n", m_Message.size());
        Message m;
        m.event = event;
        m.str = str;
        m.num = num;
        m_Message.sendMessage(m);
    };

private:
    bool  m_bFlag;
    TMsgQue<Message> m_Message;
};

int main()
{
    Fun fun;

    ///开启线程f
    fun.start();
    std::thread t(&Fun::f, &fun);

    Event event = init;
    for(size_t i = 0; i < 10; i++)
    {
        if (i % 3 == 0)
        {
            event = init;
        }
        else if (i % 3 == 1)
        {
            event = first;
        }
        else if (i % 3 == 2)
        {
            event = second;
        }

        ///主线程是生产者,调用消费者的sendMessage函数发消息给子线程处理
        ///子线程异步处理消息,不会影响主线程功能
        fun.sendMessage(event, "hello", i);
    }

    while(1)
    {}

    fun.stop();
    t.join();

    return 0;
}


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值