HXC代码架构培训_解耦组件cpost
欢迎来到重庆邮电大学RoboCon的HXC战队电控培训
我们是一群有梦想有热爱的Rcers,我们期望你能学到想要的知识,完成热爱的事情,实现宏大的梦想。
解耦组件——cpost/cevent
先决条件
- 下载源码 ,github;
- 优秀文章 作者文章cpost ;
- 优秀文章 作者文章cevent ;
前言
虽然作者是在非操作系统下设计的,但对于开放的rtos来说,它简化了复杂的rtos通讯机制,比如 消息队列,信号量,邮件,互斥锁等等设计,对于没有rtos经验和初学者的思维构建有极大帮助。
开始使用
cpost库有cpost和cevent组件
cpost 上下文切换
作者使用该组件实现异步操作,比如:在中断中抛出一个post(邮件)在循环mainloop中检测到这个post,于是执行对应的回调函数
在freertos中使用:显然,我们会有一个线程去运行这个process(处理程序)然后在中断提出post,线程运行。
缺点 :由此可见,不如在中断中释放一个信号量去唤醒一个线程来得高效,rtos上使用更是欧罗斯套娃
优点 :但当我们对于时效不是特别关心(即对于响应在10ms或者100ms都不重要时(比如低电压报警,自动控制流程(时间跨度在几十秒级别)等)),我们能十分简单的代替一些flag,同时统一的规范意味着更快的交流效率,更加愉悦的心情
cevent 基于订阅者/发布商的解耦组件
- 这是我想使用cpost组件的最主要的原因,也是本次教程的重点和架构思想构建的重点
- 订阅者/发布商的机制也许会在之后的各种开源代码,安卓开发,ros系统等等及见到,可以说是肥肠重要。
- 思想也很简单,就是有一个发布商,他会不定时的发布一些消息(可以理解为一个事件,或者说某个flag置位了(flag=1;)),但是显然并不是所有人都关心这个事件,只有订阅者才会接收到这个事件,并进行相应处理
- 在cevent里面,有核心函数 ceventPost 和核心宏 CEVENT_EXPORT 每一个EXPORT了的函数就是一个订阅者,它订阅了事件号(事件ID)而每一处调用了ceventPost的地方就是一个发行商并且发行(传播)了一个事件
cevent的优缺点
优点 :可以说是十分完美的解耦组件,即解决了统一规范问题,效率问题还解决了复杂状态设计问题
缺点 :由于所有订阅者的函数都在ceventPost函数中被调用,所以不应该设计delay等函数在其中,对于中断中使用需要考虑使用的处理时间(ps:言重了,一般放心使用,不过一定不要有delay,否则可能导致后面的函数被迫等待或者死在中断里面)
cevent的实际使用
- 良好的规范,由于解偶了所以不能出现以下代码
CEVENT_EXPORT(0, handler1, (void *)a);
你想想,要是你看到这个函数订阅事件id是0,0是啥事件啊,如何转跳啊,参数a是啥啊,handler1干啥啊,只能说炸开
改成
CEVENT_EXPORT(CEVENT_ID_LowPower, ShotDown_handler, (void *)CurrentCFG);
你一看就知道这是低电量事件(CEVENT_ID_LowPower),于是你要进行关机处理(ShotDown_handler),而且还要带参数,参数是CurrentCFG.
- 注释 由于解耦,我们其实很不好知道到底一个event有几个handler,所以在每一个event_id的#define处添加注释说明有哪些函数会是一个很棒的习惯
struct{
CEVENT_ID_LowPower=0U,//调用ShotDown_handler ShowError_handler SaftCheck_handler
CEVENT_ID_FinshShot,//调用 没有
...
}
3.思维突破
首先,一个event可以被多个函数订阅,但我们不能能指定哪个函数先调用,但是我们可以通过多个event串联实现函数调用的有序化,比如函数a响应了event1,然后函数a再抛出event1_1使得函数a_1被调用,以此类推可以调用函数a_2,a_3,a_4.
其次,我们可以和cpost联动实现异步解耦操作,实现就是在handler里面调用cpost就好
总结
本次介绍模块化组件cpost,包含cpost/cevent,是个十分简单而且无依赖的开源库,希望能对大家有所启发