文章主题  

在我们的日常编程中,对消息队列的需求非常常见,使用一个简洁、高效的消息队列编程模型,对于代码逻辑的清晰性,对于事件处理的高效率来说,是非常重要的。这篇文章就来看看 ZWave 中是通过什么机制为我们提供了一个便捷的消息队列处理机制。

内容导航  

  • 消息队列是什么

  • 我自己写的消息队列

  • ZWave 消息队列的结构

  • ZWave 消息队列的使用(初始化、存储消息、取出消息)

消息队列是什么  

消息队列最主要特点是:存储消息,先进先出。

比如在典型的生产者-消费者编程模型中,先创建一个消息队列,最大容量是 100。

当生产者产生一条消息时,如果消息队列未满,就放进消息队列的尾部。

消费者定期去检查消息队列中是否有消息,如果有,则取出最前面的那条消息进行处理,直到把队列中的所有消息都处理完。

当然,如果链表来创建一个动态的消息队列也是可以的,这样就可以构成一个无容量限制的队列,这个模型有点复杂,咱们暂且不讨论它S。

 我自己写的消息队列  

在我自己的开发过程中,经常需要使用消息队列来保存多条消息,每一条消息都存储长度不等的字符串,于是就自己写了一个最简单的消息队列实现模板,当然对于项目来说也是最合适的,因为是量体裁衣嘛。

一共2个文件(.h, .c),每次项目中需要用到时,就把这2个文件拷贝过来,再简单修改一下(保存的每条消息满足应用的需求),就直接用上了。简单、粗暴、有效、好用,每次都能很块就解决我的问题。

这里简单截个图,如果需要,我可以免费分享!

使用起来也比较简单,只需要3个步骤。

ZWave 消息队列的结构  

ZWave SDK 的每一个 Sample 中已经给我们提供了一个很好的消息队列编程模型,不过它还嵌入了一个 task 任务管理的机制,后面我会简单画一下 task 的处理逻辑,但是不会深入探究。

先来看一下 ZWave 提供的消息队列的结构。

请注意:这是消息队列的结构,而这个队列中存储的每一条消息是存储在一个数组缓冲区中,通过 array 指针进行引用。因此,在消息队列初始化的时候,必须提供一个数组,并把数组的地址赋值给 array 指针。

关于这个数组,从代码中可以看到 QElementType 其实就是一个无符号字节,因此,这个消息队列仅仅能存储最最简单的消息,即:一个字节的数值。可以看一下 SwitchOnOff.c 中所存储的消息,都是 EVENT_APP 这个枚举类型的值。

ZWave 消息队列的使用  

1.消息队列的初始化

在应用程序初始化的时候,ZWave 实例程序为我们已经创建好一个消息队列了,流程如下。

可以看到,一共有 2 个消息队列:eventQueue 和 jobQueue,这两个队列的实现机制都是一样的,只不过是把不同类型的消息放在不同的队列而已,因此,只要分析其中一个 eventQueue 就可以了。

初始化完成之后,存储消息的数组是空的,消息队列的有效消息个数是 0。

2.存储消息到消息队列

就是把一条新消息放入消息队列的数组中,然后更新消息队列的一些状态参数,比如:有效消息长度,存储的这条消息位置等等。

函数调用流程如下。

3.从消息队列中获取消息

这个也很好理解,就是通过消息队列的结构检查一下是否有消息等待处理。如果是的话,就取出消息,并更新消息队列的一些状态参数。

函数调用流程如下。

ZWave 文档中已经说明,协议层会定期调用应用层的函数 ApplicationPoll( ) ,这也是 ZWave 推荐的方式让应用层执行自己的逻辑,但是应用层不能在这个函数中执行太长时间。

在这个函数中,我们可以直接去消息队列中取出一个消息。但是如果这么做的话,就浪费了 ZWave 为我们提供的 Task 机制,因此这里调用了 TaskApplicationPoll( ),然后我们应用层的事件处理函数 AppStateManager( ) 就老老实实的待着,等待别人把事件消息准备好、喂过来。

其实,这也是一种分层编程思想,如下。

总结  

现在再回头看一下 ZWave 的消息队列处理机制,思路非常清晰,而且扩充性非常强。

后面我希望自己可以抽一点时间,把这里的代码抽取出来,写一个通用的、能够处理一些复杂消息的消息队列机制,让开发过程变得更加愉悦!


  1. 欢迎转载,请尊重版权,保留全部内容并注明来源。
  2. 如果这篇文章侵犯了您的权益,请在此处或微信公众号留言,我会及时处理。

  3. 如果需要一块探讨,请联系下面微信公众号

ZWave 中的消息队列机制的更多相关文章

  1. Handler机制中的消息队列

    --> 学习自蘑菇街大佬 Handler机制可以看成是一个消息阻塞队列,当有消息时立即处理消息,没有消息时则阻塞.在Android系统中APP启动后很快进入死循环,不断读取MessageQueu ...

  2. 工业物联网或系统集成中应用消息队列(ActiveMQ,C#的demo)的场景全面分析

    1.[连载]<C#通讯(串口和网络)框架的设计与实现> 2.[开源]C#跨平台物联网通讯框架ServerSuperIO(SSIO)介绍 2.应用SuperIO(SIO)和开源跨平台物联网框 ...

  3. 安卓中的消息循环机制Handler及Looper详解

    我们知道安卓中的UI线程不是线程安全的,我们不能在UI线程中进行耗时操作,通常我们的做法是开启一个子线程在子线程中处理耗时操作,但是安卓规定不允许在子线程中进行UI的更新操作,通常我们会通过Handl ...

  4. C#中使用消息队列RabbitMQ

    在C#中使用消息队列RabbitMQ 2014-10-27 14:41 by qy1141, 745 阅读, 2 评论, 收藏, 编辑 1.什么是RabbitMQ.详见 http://www.rabb ...

  5. GaussDB(DWS)中共享消息队列实现的三大功能

    摘要:本文将详细介绍GaussDB(DWS)中共享消息队列的实现. 本文分享自华为云社区<GaussDB(DWS)CBB组件之共享消息队列介绍>,作者:疯狂朔朔. 1)共享消息队列是什么? ...

  6. .NET中的消息队列

    下文参考:http://hi.baidu.com/21tian/blog/item/ce5464097ddf10cb3ac76335.html为何使用消息队列 您可能认为您能够通过一个简单的数据库表( ...

  7. Android 消息队列机制

    在非UI线程使用Handler进行线程通信时,一般都需要进行3个步骤: 创建Looper Looper.prepar() 创建Handler 启动消息循环Looper.loop() 通过这3步,基本就 ...

  8. 在C#中使用消息队列RabbitMQ

    1.什么是RabbitMQ.详见 http://www.rabbitmq.com/. 作用就是提高系统的并发性,将一些不需要及时响应客户端且占用较多资源的操作,放入队列,再由另外一个线程,去异步处理这 ...

  9. 如何应用.NET中的消息队列服务

    建立一个队列是应用MSMQ的第一步.您可以通过Windows计算机管理控制台中的消息队列选项完成这一操作,或者自己编程建立一个队列.列表A中的C#代码建立了一个新的私有MSMQ消息队列(如果不存在队列 ...

随机推荐

  1. HDU3117

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3117 题目大意:对于给定的一个数 n ,求斐波那契数F(n).对于超过八位的数,给出首末四位即可. 解 ...

  2. CF861D

    题目链接:http://codeforces.com/contest/861/problem/D 解题思路: 优雅的暴力. 对于输入的每一个号码,从短到长找出它的所有子串,用 vector 保存每个号 ...

  3. 【MySQL】详细说下MySQL删除数据的过程是什么样的?

    drop table 这里先介绍一下[InnoDB]存储表空间概念: Innodb存储引擎,可将所有的数据库数据存放于[ibdata1]的共享表空间:也可以将每张表存放于独立的.idb文件的独立表空间 ...

  4. mybatis的一堆多映射使用配置

    自己仿站jeep官网在制作商城时,商品详情页面需要带着一个商品的信息,商品的配置,配置对应的颜色,商品的图片   如图 首先设计业务bean 一辆车的信息 业务一对多的大业务bean,继承Car.ja ...

  5. 【JavaScript数据结构系列】06-双向链表DoublyLinkedList

    [JavaScript数据结构系列]06-双向链表DoublyLinkedList 码路工人 CoderMonkey 转载请注明作者与出处 1. 认识双向链表 不同于普通链表/单向链表,双向链表最突出 ...

  6. DQN(Deep Q-learning)入门教程(四)之Q-learning Play Flappy Bird

    在上一篇博客中,我们详细的对Q-learning的算法流程进行了介绍.同时我们使用了\(\epsilon-贪婪法\)防止陷入局部最优. 那么我们可以想一下,最后我们得到的结果是什么样的呢?因为我们考虑 ...

  7. 【Spring】JdbcTemplate的使用,查询,增、删、改

    数据库名:taobaodb 配置文件: JdbcTemplate主要提供以下五类方法: execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句: update方法及batchUpdat ...

  8. golang内存逃逸

    golang程序变量会携带油一组校验数据,用来证明它的整个生命周期是否在运行时完全可知.如果变量通过了这些校验,它就可以在栈上分配.否则就说它逃逸了,必须在堆上分配     能引起变量逃逸到堆上的典型 ...

  9. java实现第七届蓝桥杯阶乘位数

    阶乘位数 阶乘位数 9的阶乘等于:362880 它的二进制表示为:1011000100110000000 这个数字共有19位. 请你计算,9999 的阶乘的二进制表示一共有多少位? 注意:需要提交的是 ...

  10. python—socket编程

    一:客户端/服务器 架构 1.硬件C/S架构:(例如,打印机) 2.软件C/S架构:互联网中处处是C/S架构 腾讯作为服务端为你提供视频,你得下个腾讯视频客户端才能看它的视频 C/S架构与socket ...