跳转至

活动对象框架

为嵌入式应用设计一套Activity框架,做个记录,思路大量借鉴了QP框架,但逻辑不使用QML状态机。

一个Activity,就是对象维护的线程+接收事件的队列+一系列事件处理逻辑。

Activity收到事件后,对事件作出相应,执行相应操作。

系统的任意部分都可以产生事件,比如软中断处理函数、别的线程,但处理事件的只有activity。

目的

  • 模块间解耦,以发送事件的方式代替直接call
  • 实现异步执行,call的串行化变相地实现了锁(同一时刻只处理一个事件),简化模块内部处理多线程同步问题
  • 一些操作可以invoke到目标activity中执行,可以将逻辑实现写在发送者这边,避免代码分散
  • 方便实现全局事件,比如通知系统即将断电(模块需要保存一些信息)
  • 方便实现发行-订阅机制,任意一个模块(不一定是activity)都可以发行事件,而activity拥有接收槽可以接收事件

功能点

  • Activity的索引,小系统可以使用唯一编号,更大的系统用字符串似乎更好些
  • 带优先级
  • 延时执行,比如模块说“在xx秒后执行xxx函数”,比如方便做定时轮询、异步操作超时判断等,但时间太长会影响模块反初始化,所以得做被打断后的异常通知(在参数里传个)(不一定在这模块内实现)
  • 为了方便做安全退出,activity需要有“即将反初始化禁止接收”的状态,以方便退出时清掉消息队列(可以查到这个状态以加速过程,比如异步执行的操作可能会很长时间);需要退出时,禁止新数据接收,并向队列发发送一个“退出事件”,待

编程范式

  • Activity间不共享内存资源
  • Activity在处理事件时尽可能不阻塞

难点

内存管理

VxWorks的做法是把事件相关的数据全压进消息队列里,代价很高。

QP框架的做法是在框架内做一个公用的EventPool用来存放事件相关的内存:

1560094255519

事件的生产者从这里申请内存(初期可以用malloc实现),由于框架维护着Activity的线程,所以是能知道事件什么时候被处理完的,处理完后自动释放。

同时会有一些事件的参数很小,无需动态内存,这类事件得有一个静态内存的标记

当接收方不止一个时,这套管理方法就得加上引用计数器了,一开始不打算支持这功能。