现有版本的QP有QP/C、QP/C++和QP/nano.
QP由4大部分组成:事件处理器QEP(Quantum Event Processor) 、轻量级的事件驱动框架QF(Quantum Framework)、任务调度微内核QK(Quantum Kernel)、实时跟踪调试器QS(Quantum Spy)。
QEP:
是一个可继承、可移植的、可重用的状态机引擎,用来处理与UML(Unified Modeling Language,统一建模语言)状态机信号相关的事件。
QEP的核心思想就是,用一个函数指针指向当前状态函数,使用这个函数指针有条件地执行某状态函数,并根据执行结果执行其它的相应动作。
(1)状态函数指针
QP中的状态用函数表示,这类函数叫状态函数,一个状态函数可以表示一个状态,系统 中存在多少个状态,就需要多少个函数来表示他们。
在QEP中有一个状态函数指针QStateHandler的定义,程序可以通过这个函数指针来应用任何一个状态函数。在状态函数内的实现使用了结构化的switch-case语句,进行分类处理状态收到的不同事件。
QStateHandler 指针的定义如下:
typedef QState (*QStateHandler)(void *me, QEvent const *e);
/*状态函数指针,用来引用状态机中任何一个状态函数*/
这里的QState代表状态函数的返回值,定义如下
typedef uint8_t QState;
/*状态返回值,代表状态函数的返回值*/
QState可取如下四种返回值定义:
0---Q_RET_HANDLED, 代表事件已经得到处理,但没发生状态转换,叫内部状态转换;
1---Q_RET_IGNORED, 代表事件已被忽略,没得到处理;
2---Q_RET_TRAN, 代表事件已经得到处理,并发生了状态转换,并成功的转换到了其它的状态;
3---Q_RET_SUPER, 代表进入父状态,仅用于层次状态机中。
(2)状态机的当前状态
在有限状态机或层次状态机的内部均定义有一个state变量,其类型为一个只想状态函数的指针QStateHandler。只要这个指针指向哪个状态函数,这个状态函数就是当前的状态,当接收到一个时间时,QEP总是把这个事件给QStateHandler指针所指向的状态函数来响应。虽然具有多个状态,但状态机在同一时刻,却只能有一个“焦点”状态(即当前状态),这个“焦点”状态可以通过调用Q_TRAN(target_)来转换。
/*“焦点”变量的定义如下:*/
typedef struct QFsmTag {
QStateHandler state; /*有限状态机的当前活动状态,既常用的 me->state */
} QFsm;
typedef struct QFsmTag QHsm; /*有限状态机的数据结构*/
/*层次状态机的数据结构,其定义与有限状态机的定义是一样的*/
/*“焦点”转换的定义如下:*/
#define Q_TRAN(target_) (((QFsm *)me)->state = (QStateHandler)(target_),
Q_RET_TRAN)
QF:
量子框架 QF 是一个基于事件驱动的框架。应用程序将其所创建的事件实例均放到事件池中,并分发这些时间到已订阅这些事件的活动对象中。应用程序要订阅事件,然后当被注册的事件发生时,QF就会自动分发这些被订阅过的事件到相应的活动对象中。形象点说,可以把QF理解成一个软件总线,连接着多个的活动对象和中断服务例程,而QF的责任是对事件进行存贮、分发、形成事件驱动的模型。
QF中有两种事件分发机制:
1、直接事件分发
事件由一个活动对象直接被分发到另一个多动对象,被称为直接事件投递。利用这种方式进行事件分发,需要知道目标活动对象。
void QActive_postFIFO(QActive *me, QEvent const *e)
/*分发事件的函数*/
2、 P/S事件分发
利用QF中定义的活动对象事件订阅表,以P/S(发行/订阅)的方式投递事件。以这种方式进行事件的投递,不需要知道目标活动对象,QF会自动查找事件订阅表,以确定应该把事件投递到哪里。大大减少了活动对象之间的耦合度。
void QF_publish(QEvent const *e)