一.原理讲解
主要数据类型讲解
运用的是环形缓冲队列,没有用到链表,使用数组实现
消息里面携带的信息是,处理类型(对应该使用何种接口函数处理数据),数据长度,以及数据缓存。
typedef struct _msg_event {
unsigned int type;
unsigned int len;
unsigned char data[8];
} MSG_EVENT;
消息队列数据类型包含,消息数据,入栈消息序号,出栈消息序号以及支持的最大消息数量。
typedef struct _queue {
MSG_EVENT ev[EVENTS_MAX_SIZE];
unsigned int max_size;
unsigned int front;
unsigned int rear;
} QUEUE;
根据消息类型执行的接口函数数据类型,包含,处理类型以及回调函数。
typedef struct _ev_map {
unsigned int type;
int (*handler)(MSG_EVENT* ev, void* cookie);
} EV_MAP;
工作流程图
二.源码
源码是在windows环境下编写的应用程序,使用了多任务处理,主要是为了测试功能。可以稍微修改移植到任何平台上运行。
#include<stdio.h>
#include<time.h>
#include<windows.h>
/************消息队列处理类************/
#define EVENTS_MAX_SIZE 24
typedef struct _msg_event {
unsigned int type;
unsigned int len;
unsigned char data[8];
} MSG_EVENT;
typedef struct _ev_map {
unsigned int type;
int (*handler)(MSG_EVENT* ev, void* cookie);
} EV_MAP;
typedef struct _queue {
MSG_EVENT ev[EVENTS_MAX_SIZE];
unsigned int max_size;
unsigned int front;
unsigned int rear;
} QUEUE;
static MSG_EVENT MSG_EV_NULL[] = {
0, NULL, NULL
};
int qevent_init(QUEUE* que, unsigned int size)
{
memset(que, 0x00, sizeof(QUEUE));
que->max_size = size;
que->front = 0;
que->rear = 0;
return 0;
}
int qevent_append(QUEUE *que, MSG_EVENT* ev)
{
if ((que->rear+1)%que->max_size == que->front)
return -1;
que->ev[que->rear].type = ev->type;
que->ev[que->rear].len = ev->len;
memcpy(que->ev[que->rear].data, ev->data, ev->len);
que->rear = (que->rear+1)%que->max_size;
return 0;
}
int qevent_destory(QUEUE *que)
{
if (!que) return 1;
free(que);
que = NULL;
return 0;
}
MSG_EVENT* qevent_pop(QUEUE *que)
{
static MSG_EVENT ev;
if (que->front == que->rear)
return MSG_EV_NULL;
memset(&ev, 0, sizeof(ev));
ev.type = que->ev[que->front].type;
ev.len = que->ev[que->front].len;
memcpy(&ev.data, que->ev[que->front].data, que->ev[que->front].len);
que->front = (que->front+1)%que->max_size;
return &ev;
}
int event_init(QUEUE *qev)
{
return qevent_init(qev, EVENTS_MAX_SIZE);
}
int event_dispatch(QUEUE* qev, MSG_EVENT* msg)
{
if (!qev) return -1;
return qevent_append(qev, msg);
}
MSG_EVENT* event_fetch(QUEUE* qev)
{
if (!qev) return NULL;
return qevent_pop(qev);
}
#define EV_INVALID 0
#define EV_CFG 1
#define EV_CMD 2
#define EV_TOF_RESPOND 3
#define EV_SYS_RESPOND 4
int ev_cmd_cb(MSG_EVENT* ev, void* cookie)
{
switch (ev->data[0]){
case 1:
printf("cmd 1 \n");
break;
case 2:
printf("cmd 2 \n");
break;
case 3:
printf("cmd 3 \n");
break;
default:
printf("cmd 0 \n");
break;
}
return 0;
}
int ev_cfg_cb(MSG_EVENT* ev, void* cookie)
{
switch (ev->data[0]){
case 1:
printf("cfg 1 \n");
break;
case 2:
printf("cfg 2 \n");
break;
case 3:
printf("cfg 3 \n");
break;
default:
printf("cfg 0 \n");
break;
}
return 0;
}
int ev_tof_cb(MSG_EVENT* ev, void* cookie)
{
switch (ev->data[0]){
case 1:
printf("tof 1 \n");
break;
case 2:
printf("tof 2 \n");
break;
case 3:
printf("tof 3 \n");
break;
default:
printf("tof 0 \n");
break;
}
return 0;
}
EV_MAP event_maps[] = {
{EV_CMD, ev_cmd_cb},
{EV_CFG, ev_cfg_cb},
{EV_TOF_RESPOND, ev_tof_cb}, /* 由程序内部事件自动触发 */
{EV_INVALID, NULL}
};
QUEUE qev_main;
int sr_event_init(void)
{
int ret = 0;
ret = event_init(&qev_main);
if (ret < 0){
return -1;
}
return ret;
}
int sr_event_handle(void)
{
unsigned char i = 0;
while (1){
MSG_EVENT* ev_msg = event_fetch(&qev_main);
if (ev_msg->type == EV_INVALID)
return -1;
for (i=0; i<sizeof(event_maps)/sizeof(EV_MAP); ++i){
if (event_maps[i].type == ev_msg->type) {
if (event_maps[i].handler){
event_maps[i].handler(ev_msg, NULL);
}
}
}
}
}
/************************************/
DWORD WINAPI ThreadFun(LPVOID pM)
{
while(1){
sr_event_handle();
Sleep(100);
}
}
DWORD WINAPI ThreadFun2(LPVOID pM)
{
static MSG_EVENT ev = {
.type = 1,
.len = 1,
.data[0] = 2,
};
static MSG_EVENT ev2 = {
.type = 3,
.len = 1,
.data[0] = 3,
};
while(1){
event_dispatch(&qev_main,&ev);
event_dispatch(&qev_main,&ev2);
Sleep(300);
}
}
DWORD WINAPI ThreadFun3(LPVOID pM)
{
static MSG_EVENT ev = {
.type = 2,
.len = 1,
.data[0] = 1,
};
while(1){
event_dispatch(&qev_main,&ev);
Sleep(150);
}
}
void create_thread(void)
{
HANDLE handle = CreateThread(NULL,0,ThreadFun,NULL,0,NULL);
HANDLE handle2 = CreateThread(NULL,0,ThreadFun2,NULL,0,NULL);
HANDLE handle3 = CreateThread(NULL,0,ThreadFun3,NULL,0,NULL);
WaitForSingleObject(handle, INFINITE);
WaitForSingleObject(handle2, INFINITE);
WaitForSingleObject(handle3, INFINITE);
}
void main(void)
{
sr_event_init();
create_thread();
while(1){
}
}