消息队列的5个常见应用场景
https://segmentfault.com/a/1190000017130224
想要在单片机开发应用消息队列处理事件主要是为了解耦,减少模块与模块之间的耦合。
看过挺恶心的代码,一个事件就用一个变量做标志位,全局变量满天飞。 就想着用消息队列模仿消息驱动的机制来处理事件。
有类似这样处理的:
https://blog.csdn.net/u012210286/article/details/83313099
然而这样的话处理队列事件的函数在每次增减消息都要去改动,所以想写个每次增加消息处理函数不用修改的
实现
数据结构:
typedef struct msg_node{
void *parm;
void (*handler)(void *parm);
}msg_node_t; /* 消息数据结构 */
typedef struct msg_driver{
unsigned int in; //写入的位置
unsigned int out; //读出的位置
msg_node_t *buf[MSG_DRIVER_SIZE];
}msg_driver_t;
将消息插入到消息队列中:
这里就直接将事件的处理函数直接插入到队列中,缺点就是比较浪费资源。
bool publish_msg(msg_driver_t *msg_buf, msg_node_t *msg)
{
if( is_msg_buf_full (msg_buf) == TRUE )
{
return FALSE;
}
msg_buf->buf[msg_buf->in] = msg;
msg_buf->in = (++msg_buf->in) % MSG_DRIVER_SIZE; //防止越界
return TRUE;
}
获取消息:
static msg_node_t *get_messge(msg_driver_t *msg_buf)
{
msg_node_t *msg = NULL;
if( is_msg_buf_empty(msg_buf) )
{
return NULL;
}
msg = msg_buf->buf[msg_buf->out];
msg_buf->out = (++msg_buf->out) % MSG_DRIVER_SIZE; //防止越界
return msg;
}
从队列循环取出消息处理:
由于每次发布消息都是送的处理函数指针,所以处理函数都不用修改。
void message_driver_handle(msg_driver_t *msg_buf)
{
msg_node_t *msg;
while( (msg = get_messge(msg_buf)) != NULL )
{
if (msg->handler != NULL)
msg->handler(msg->parm);
}
}
简单的测试是可行
msg_driver_t msg_driver;
static void msg1_handle(void *parm)
{
printf("gets msg1\r\n");
}
static void msg2_handle(void *parm)
{
printf("get msg2\r\n");
}
static void msg3_handle(void *parm)
{
printf("do msg3\r\n");
}
msg_node_t msg1 = {
.parm = "I love u",
.handler = msg1_handle
};
msg_node_t msg2 = {
.parm = "I hate u",
.handler = msg2_handle
};
msg_node_t msg3 = {
.parm = NULL,
.handler = msg3_handle
};
publish_msg(&msg_driver, &msg1);
publish_msg(&msg_driver, &msg2);
publish_msg(&msg_driver, &msg3);
int main(void)
{
while(1)
{
message_driver_handle(&msg_driver);
}
}
应该还是可以有更好的方法,比较菜,想不出来了。