基于状态机进行实际应用的时候,会感觉有些力不从心,因为一个应用通常会被分解为多个状态机。这些状态机之间如何完成协作的,如何完成通信,优先级排列,事件派发,队列存储等等,这些需求在状态机中并没有做支持,QF的存在就对这一情况做了很好的补充。并引入了对象计算模式,抽象出了活动对象:一个对象拥有自己的控制线程,称为活动对象。
在多任务操作系统当中,每个活动对象都是保持自治的,拥有自己的控制线程(事件循环) 、事件队列 、状态机。也可以这样理解,在多任务操作环境里,使用多个事件驱动型操作系统(简单理解:一个活动对象可以当做一个单独的事件驱动型系统)。
活动对象在源码中的定义,如下:
针对控制线程还想再多说一些,并不是所有的活动对象都需要自带控制线程,当仅适用qf框架服务时,一个名为QV的合作式内核来解决所有的活动对象的控制线程的问题,因为大家的操作都是一样的,获取事件、分发事件、处理事件(所以它被从活动对象中抽了出来了)下图是简化版的活动对象的系统及事件循环:
以活动对象为核心的应用程序开发,活动对象其服务的提供,可能来源于两部分,QF框架和RTOS系统。从另一个角度我们来看一下,应用,QF框架,RTOS系统之间的关系,如图:
从图中可以看到他们的关系,有一点还想要说一下,QF框架的本质是提供服务的,他的下面可以有RTOS也可以没有,那么问题就来了,如果底层是RTOS,那么QF可以借用他的一些服务,例如消息队列,例如内存管理等。假如QF的下面就是裸机。那么关于他需要的资源就需要他自己实现了,例如一颗合作式的内核QV就可能被集成到QF上,关于QV合作式内核后面单独聊吧。
活动对象在应用过程中,你需要理解他最核心的三个设定:
1. 异步通讯,活动对象拥有自己的事件队列,并且通过从事件队列中获取事件,所以事件都是被异步投递的,站在事件生产者的角度,异步通讯就意味着,他只负责生产一个事件,并将其发送给相应的活动对象,并不原地等待事件的处理。
2. RTC————运行到完成,也就是运行到完成的过程中不被打断,这么说还是比较模糊的,正确的理解应该是,状态机在处理一个事件的过程中,不会去接收和处理其它事件,只有等这个事件处理完了,才可以去处理其它事件。这个过程是不会被打断的。
3. 封装,这个可能是活动对象最重要的概念,其实应该是面向对象的概念,封装意味着不共享数据和其它任意资源。
接下来进入实战部分,这一部分不要看源码了,源码太精彩了,后面单独拉出来给大家分析分析,原来C语言可以这么玩,基于QP6.9.1开发者文档中中找到关于活动对象相关的API函数,并分析一下其函数功能、参数、及返回值:
关于如何创建一个活动对象并启动对应的活动对象步骤,如下:
1. 定义具体的活动对象类型(类比于定义结构体类型),如下:
2.有了类型以后,实例化活动对象(类似于创建变量),如下:
3.构造活动对象(类比于变量初始化),如下:
4.启动活动对象(类比喻执行Table_intial函数),如下:
5.停止活动对象相关操作并没有显示的调用,表明这个应用不需要停止活动对象。