博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
架构实践 - 3. 基于事件系统的demo
阅读量:4041 次
发布时间:2019-05-24

本文共 16538 字,大约阅读时间需要 55 分钟。

1、概述

基于上篇文章,我们设计一个具体的demo。demo在linux版本运行,gcc编译通过

主要由如下文件构成:

main.c                  实现main_loop, 和main_handler

base_queue.c/h   实现队列模块

base_timer.c/h     实现timer模块

Makefile               编译文件,直接使用make编译就行

其他依赖文件

lish.h common.h 

2、运行

 

3、源码

main.c 

#include 
#include
#include
#include
#include "common.h"#include "base_queue.h"#include "base_timer.h"extern int msgqid;tmr_hdl_t tmr_hdl = NULL;/** * func: request event handler * parm: * return: */void main_request_handler(request_t *req){ switch(req->type) { case POWER_ON: printf("req msg.power_on.id=%d, name=%s\n", req->msg.power_on_req.id, req->msg.power_on_req.name); break; case POWER_OFF: printf("req msg.power_off.id=%d, name=%s\n", req->msg.power_off_req.id, req->msg.power_off_req.name); break; default: printf("not support the request!\n"); break; }}/** * func: pthread, trans * parm: * return: */void *pthread(void *arg){ int rc, timeout, ret; msg_t msg = {0}; ms_t ms = 0; printf("start pthread %s...\n", ((data_t*)arg)->name); while(1) { /* 1. read event from queue */ // msgrcv(msgqid, &msg, sizeof(msg)-sizeof(long), QUEUE_TYPE, 0); ret = msgrcv(msgqid, &msg, sizeof(msg)-sizeof(long), QUEUE_TYPE, IPC_NOWAIT); /* 2. trans message to msg handler */ if (ret > 0) { request_t *req = (request_t *)msg.mdata; // printf("request->typed=%d, msg.id=%d, msg.name=%s\n", // req->type, msg.mtype, msg.mdata); main_request_handler(req); } /* 3. get the remain time of the recent timer, not using here */ rc = get_next_timeout(tmr_hdl, &ms); if (rc < 0) { timeout = 1000; } else { timeout = ms; } /* 4. update system timer */ time_update(tmr_hdl); /* 5. execute callback, if the timer is end */ proc_timer(tmr_hdl); usleep(1*1000); //sleep 1ms }}/** * func: test request function1 * parm: * return: */void func_demo1(){ power_on_req_t req = {0}; req.id = 1; memcpy(req.name, "power_on", sizeof("power_on")); POST_REQUEST(POWER_ON, &req, sizeof(req), NULL, NULL);}/** * func: test request function2 * parm: * return: */void func_demo2(){ power_off_req_t req = {0}; req.id = 2; memcpy(req.name, "power_off", sizeof("power_off")); POST_REQUEST(POWER_OFF, &req, sizeof(req), NULL, NULL);}/** * func: test timer * parm: * return: */void timer_handler(int timer_id, void* data){ printf("lyh add -> enter timer_handler\n");}/** * func: * parm: * return: */int main(){ printf("Hello World\n"); pthread_t p_hander = 0; tmr_t main1_tmr={0}, main2_tmr={0}; /* queue init */ queue_init(); /* timer init */ tmr_hdl = timer_init(); /* create pthread */ data_t data = {.num=1, .name="test"}; pthread_create(&p_hander, NULL, pthread, (void*)(&data)); /* test request event */ func_demo1(); func_demo2(); /* test timer */ start_tmr(tmr_hdl, &main1_tmr, timer_handler, 1 * 1000 / MS_PER_TICK); start_tmr(tmr_hdl, &main2_tmr, timer_handler, 10 * 1000 / MS_PER_TICK); while(1) { sleep(1); }}

 

base_queue.c

#include "base_queue.h"int msgqid = 0;  /* message queue *//** * func: init queue * parm: * return: */int queue_init(){    key_t key;    key = ftok("./", 1024);    /* create queue */    msgqid = msgget(key, IPC_CREAT|0666);    return 0;}/** * func: post message to queue * parm: * return: */int post_request_async(req_type_t type, const void* req, unsigned int size, prot_rsp_cb_t routine, const void* priv){    // printf("enter post_request_async\n");    /* 1. create queue message */    msg_t *msg = malloc(sizeof(msg_t));    msg->mtype = QUEUE_TYPE;    /* transform request to quue message */    request_t *request = (request_t *)(msg->mdata);    /* 2. fill queue message */    request->type = type;    memcpy(&(request->msg), req, size);    request->cb_func = routine;    request->priv = priv;    /* 3. seed message */    return msgsnd(msgqid, (void *)msg, sizeof(msg_t)-sizeof(long), 0);}

 

base_queue.h

#ifndef _BASE_QUEUE_H_#define _BASE_QUEUE_H_#include 
#include
#include
#include "common.h"#define QUEUE_TYPE 10#define POST_REQUEST(type, req, size, routine, priv) \ post_request_async(type, req, size, routine, priv)/* request message type */typedef enum { POWER_ON, POWER_OFF,} req_type_t;/* message data1 */typedef struct { int id; char name[20];} power_on_req_t;/* message data2 */typedef struct { int id; char name[20]; void *p;} power_off_req_t;/* message callback */typedef void (*prot_rsp_cb_t)(int, const void*, void*);/* request type */typedef struct { req_type_t type; /* support request message type */ union { power_on_req_t power_on_req; power_off_req_t power_off_req; } msg; /* support request message */ prot_rsp_cb_t cb_func; /* callback */ const void* priv; /* priv will be passed back in cb_func */} request_t;/* queue message */typedef struct msg{ long mtype; char mdata[sizeof(request_t)];} msg_t;extern int msgqid; /* message queue */int queue_init();int post_request_async(req_type_t type, const void* req, unsigned int size, prot_rsp_cb_t routine, const void* priv);#endif //_BASE_QUEUE_H_

 

base_tiemr.c

#include 
#include
#include "base_timer.h"typedef struct tmr_cb { list_t tmr_list; int init; int tmr_cnt; volatile ms_t sys_msec;} tmr_cb_t;static volatile ms_t sys_msec;/* t1 is earlier than t2 */#define time_before(t1, t2) ((long long)((t1)-(t2)) <= 0)#define timer_before(tmr1, tmr2) (time_before(tmr1->expire, tmr2->expire))/** * Update the current time. * Because all timer's expiring time is relative to current time, so we must * update current time after each time-consuming operations, e.g. epoll_wait. */void time_update(tmr_hdl_t hdl){ int rc; static struct timespec tp; /* get system time, and save to timer */ rc = clock_gettime(CLOCK_MONOTONIC, &tp); if (rc < 0) abort(); ((tmr_cb_t*)hdl)->sys_msec = (ms_t)(tp.tv_sec * 1000) + (ms_t)(tp.tv_nsec)/(1000*1000); return;}/** * Create a timer list */tmr_hdl_t timer_init(){ tmr_cb_t* thdl = (tmr_cb_t*)malloc(sizeof(tmr_cb_t)); if (!thdl) return NULL; /* create timer list */ list_init(&(thdl->tmr_list)); /* update timer */ time_update(thdl); thdl->tmr_cnt = 0; return (tmr_hdl_t)thdl;}/** * Delete a timer list */void timer_deinit(tmr_hdl_t hdl){ list_node_t *node, *tmp; tmr_t *tmr; tmr_cb_t* tmr_cb = hdl; list_for_del(&(tmr_cb->tmr_list), node, tmp) { tmr = object_of(tmr_t, self, node); list_del(&(tmr->self)); tmr_cb->tmr_cnt--; } free(hdl);}/** * Place the timer into timer queue. */void add_timer(tmr_hdl_t hdl, tmr_t* timer){ list_node_t* node; tmr_t* tmr; tmr_cb_t* tmr_cb = hdl; timer->expire = tmr_cb->sys_msec + timer->val * MS_PER_TICK; list_for(&(tmr_cb->tmr_list), node) { tmr = object_of(tmr_t, self, node); //get timer addr from node if (timer_before(timer, tmr)) { break; } } list_node_init(&(timer->self)); list_ins_before(node, &(timer->self)); tmr_cb->tmr_cnt++;}/** * Delete the timer from timer queue. */void del_timer(tmr_hdl_t hdl, tmr_t* timer){ tmr_cb_t* tmr_cb = hdl; if (timer->self.next != NULL && timer->self.prev != NULL) { list_del(&(timer->self)); tmr_cb->tmr_cnt--; }}int timer_is_running(tmr_t *timer){ if (timer->self.next != NULL && timer->self.prev != NULL) { return 1; } return 0;}/** * Do callbacks for all the expired timer, restart the timer * if it's repeatitive. */void proc_timer(tmr_hdl_t hdl){ tmr_t* tmr; list_node_t *node; tmr_cb_t* tmr_cb = hdl; for (;;) { if (tmr_cb->tmr_cnt == 0) { break; } node = list_first(&(tmr_cb->tmr_list)); tmr = object_of(tmr_t, self, node); if (time_before(tmr->expire, tmr_cb->sys_msec)) { del_timer(hdl, tmr); if (tmr->repeat) { add_timer(hdl, tmr); } tmr->fn(tmr->timer_id, tmr->data); } else { break; } }}/** * Find out how much time can we sleep before we need to * wake up to handle the timer. */int get_next_timeout(tmr_hdl_t hdl, ms_t* tick){ list_node_t* node; tmr_t* tmr; tmr_cb_t* tmr_cb = hdl; *tick = 0; if (tmr_cb->tmr_cnt == 0) { /* no timer yet */ return -1; } node = list_first(&(tmr_cb->tmr_list)); tmr = object_of(tmr_t, self, node); if (time_before(tmr->expire, tmr_cb->sys_msec)) { *tick = 0; } else { *tick = tmr->expire - tmr_cb->sys_msec; } return 0;}

base_tiemr.h

#ifndef TIMER_H#define TIMER_H#include "list.h"#define MS_PER_TICK      5         /* milli-seconds per tick */typedef unsigned long long ms_t;typedef void* tmr_hdl_t;typedef void (*timer_func_t)(int timer_id, void* data);/** * timer struct data*/typedef struct {    list_node_t    self;    int            timer_id;        /* timer id */    unsigned       val;             /* how many ticks? */    ms_t           expire;          /* timer left */    int            repeat;          /* timer repeat time */    timer_func_t   fn;              /* timer end, callback */    void           *data;} tmr_t;/** * start timer without data **/#define start_tmr(hdl, tmr, func, to)           \    do {                                        \        (tmr)->val = to;                        \        (tmr)->timer_id = 0;                    \        (tmr)->data = NULL;                     \        (tmr)->fn = func;                       \        (tmr)->repeat = 0;                      \        del_timer(hdl, (tmr));                  \        add_timer(hdl, (tmr));                  \    } while (0)/** * start timer without data & timer id **/#define start_tmr_with_data_id(hdl, tmr, func, to, d, id)       \    do {                                                        \        (tmr)->val = to;                                        \        (tmr)->timer_id = id;                                   \        (tmr)->data = d;                                        \        (tmr)->fn = func;                                       \        (tmr)->repeat = 0;                                      \        del_timer(hdl, (tmr));                                  \        add_timer(hdl, (tmr));                                  \    } while (0)/** * start timer without data **/#define start_tmr_with_data(hdl, tmr, func, to, d)      \    do {                                                \        (tmr)->val = to;                                \        (tmr)->timer_id = 0;                            \        (tmr)->data = d;                                \        (tmr)->fn = func;                               \        (tmr)->repeat = 0;                              \        del_timer(hdl, (tmr));                          \        add_timer(hdl, (tmr));                          \    } while (0)/** * start timer, and repeat **/#define start_rpt_tmr_with_data(hdl, tmr, func, to, d)  \    do {                                                \        (tmr)->val = to;                                \        (tmr)->timer_id = 0;                            \        (tmr)->data = d;                                \        (tmr)->fn = func;                               \        (tmr)->repeat = 1;                              \        del_timer(hdl, (tmr));                          \        add_timer(hdl, (tmr));                          \    } while (0)extern tmr_hdl_t timer_init(void);extern void timer_deinit(tmr_hdl_t);extern void add_timer(tmr_hdl_t, tmr_t*);extern void del_timer(tmr_hdl_t, tmr_t*);extern void proc_timer(tmr_hdl_t);extern int get_next_timeout(tmr_hdl_t, ms_t*);extern void time_update(tmr_hdl_t);extern int timer_is_running(tmr_t *);#endif

 

list.h

#ifndef LIST_H#define LIST_H#include 
struct list_node;typedef struct list_node list_node_t;typedef struct list_node list_t;struct list_node { list_node_t* next; list_node_t* prev;};/* * For macros. */#define list_for(l, nd_var) for (nd_var = (void*)((l)->next); \ (nd_var != (void*)(l)) && (nd_var != NULL); \ nd_var = (void*)((list_node_t*)nd_var)->next)#define list_for_del(l, nd_var, tmp_var) for (nd_var = (void*)((l)->next); \ tmp_var = (void*)((list_node_t*)nd_var)->next, \ nd_var != (void*)(l) || (nd_var = NULL); \ nd_var = tmp_var)/* * Basic node level operations. */static inline voidlist_ins_after(list_node_t* nd, list_node_t* new_nd){ // printf("list_ins_after %p %p\n", nd, new_nd); // list_print(nd, "ins_after in"); new_nd->next = nd->next; new_nd->prev = nd; nd->next->prev = new_nd; nd->next = new_nd; // list_print(nd, "ins_after out");}static inline voidlist_ins_before(list_node_t* nd, list_node_t* new_nd){ // list_print(nd, "ins_before in"); new_nd->prev = nd->prev; new_nd->next = nd; nd->prev->next = new_nd; nd->prev = new_nd; // list_print(nd, "ins_before out");}static inline void*list_del(list_node_t* nd){ // list_print(nd, "del in"); nd->prev->next = nd->next; nd->next->prev = nd->prev; // list_print(nd->next, "del out"); nd->next = NULL; // just to be safe nd->prev = NULL; // just to be safe return nd;}/* * High-level operations. */static inline voidlist_init(list_t* l){ l->next = l; l->prev = l;}static inline voidlist_node_init(list_node_t* nd){ nd->next = nd; nd->prev = nd;}static inline intlist_is_empty(list_t* l){ return (l == l->next);}static inline void*list_next(list_t* l){ return (list_is_empty(l) ? NULL : l->next);}static inline void*list_prev(list_t* l){ return (list_is_empty(l) ? NULL : l->prev);}static inline void*list_first(list_t* l){ return list_next(l);}static inline void*list_last(list_t* l){ return list_prev(l);}static inline voidlist_ins_front(list_t* l, list_node_t* nd){ list_ins_after(l, nd);}static inline voidlist_ins_back(list_t* l, list_node_t* nd){ list_ins_before(l, nd);}static inline void*list_del_front(list_t* l){ return (list_is_empty(l) ? NULL : list_del(l->next));}static inline void*list_del_back(list_t* l){ return (list_is_empty(l) ? NULL : list_del(l->prev));}/* * */static inline voidlist_enqueue(list_t* l, list_node_t* nd){ list_ins_back(l, nd);}static inline void*list_dequeue(list_t* l){ return list_del_front(l);}/* * */static inline voidlist_push(list_t* l, list_node_t* nd){ list_ins_front(l, nd);}static inline void*list_pop(list_t* l){ return list_del_front(l);}/* * */static inline voidlist_transfer(list_t *src, list_t *dst){ list_node_t *nd; while ((nd = list_dequeue(src)) != NULL) { list_enqueue(dst, nd); }}/* * */static inline unsigned intlist_count_slowly(list_t *l){ list_node_t *nd; unsigned int cnt = 0; list_for(l, nd) { cnt++; } return cnt;}/** * list_splice - join two lists. result list would be (src + dst) and * src list head will be re-initialized. * @src: the new list to add. * @dest: the place to add it in the first list. */static inline voidlist_splice(list_t *src, list_t *dst){ if (!list_is_empty(src)) { list_t *first = src->next; list_t *last = src->prev; list_t *at = dst->next; first->prev = dst; dst->next = first; last->next = at; at->prev = last; list_init(src); }}/** * get type struct addr from ptr **/#define object_of(type, member, ptr) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})#endif

common.h

#ifndef _COMMON_H_#define _COMMON_H_#include 
#include
typedef struct data{ int num; char *name;} data_t;#endif

 

Makefile

#表示用的编译器CC = gcc#表示编译时的动作,-Wall 小心的, -g可调试的。CC_FLAGS = -Wall -g# 加载动态库SO = -lpthread#目标文件all:demo#加载编译文件SRCS = $(wildcard ./*.c)#执行动作demo:$(SRCS)	$(CC) $(CC_FLAGS) $^ -o $@ $(SO)clean:	rm -f demo *.o *.exe

 

 

 

喜欢就支持一波哦~

转载地址:http://moldi.baihongyu.com/

你可能感兴趣的文章
多线程使用随机函数需要注意的一点
查看>>
getpeername,getsockname
查看>>
让我做你的下一行Code
查看>>
浅析:setsockopt()改善程序的健壮性
查看>>
关于对象赋值及返回临时对象过程中的构造与析构
查看>>
VS 2005 CRT函数的安全性增强版本
查看>>
SQL 多表联合查询
查看>>
Visual Studio 2010:C++0x新特性
查看>>
drwtsn32.exe和adplus.vbs进行dump文件抓取
查看>>
cppcheck c++静态代码检查
查看>>
在C++中使用Lua
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>
可以在线C++编译的工具站点
查看>>
关于无人驾驶的过去、现在以及未来,看这篇文章就够了!
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
为什么读了很多书,却学不到什么东西?
查看>>
长文干货:如何轻松应对工作中最棘手的13种场景?
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>