"所谓专家, 就是犯了在他那个领域内能犯的所有错误的人."
作者本人大胆下断语:类 == 有状态的过程 == 状态机。
QF的2个基本概念: 1. 层次状态机 2. 基于活动对象的编程模型QF直接将以上2个概念映射到了源代码,而不需要中间的图形化的View
有限状态机的本质
针对离散系统, 在某些阶段, 系统保持一定的质.
Mealy, Moore状态机的区别
Mealy: 输出是输入和现有状态的函数. 描述形式多数情况下较Moore简单,所以便于工程实现.
Moore: 输出时现有状态的函数.逻辑关系简单,便于数学分析.
状态图和流程图的区别
与状态图相比,流程图颠倒了顶点和弧的意义.状态图中,处理关联于弧;而在流程图中,处理关联于顶点.
状态机的执行环境
状态机不能在真空中运行.除了
事件处理器外,一个状态机的执行环境还包括
执行上下文(线程),
事件排队,
事件发送和
定时服务.这些元素强烈依赖于操作系统和应用领域的支持.
QF--量子框架
QF捕获了在嵌入式实时环境下执行并发状态机的全部机构.
QF中分解的主要元素是
活动对象.也可以成为状态机对象.类似于I-Logix Rhapsody中的OXF"对象执行框架"
活动对象之间通过发送/接收事件来通信.
活动对象最重要的特性是它不透明的封装壳.它将活动对象内部结构与外部环境严格地分开来,只有事件实例可以穿越这个壳.
与其他CASE工具不同,QF不关心激励或仪器化状态机的设施,不偏爱自动化代码生成. QF只实现了最基本的基于活动对象的计算模型,该模型只限于在单级分解的活动对象间的异步事件交换.
并发系统,本质上是运行资源之于代码的时域分配.
多进程的运行资源指cpu,和mem;多线程则主要指cpu.
传统的多任务操作系统为解决竞争条件,都提供了同步互斥机制.
但并发多任务系统有一个难以解决的固有问题--死锁.
特别注意,
共享内存这一古老的通信手段只适用于同一个地址空间.
由于活动对象不共享数据,并仅仅通过事件实例通信,所以他们不需要在同一个地址空间执行.
QF不象传统的并发方法那样将软件的信号延迟隐藏起来,它将软件延迟暴露在程序员面前.
基于活动对象的系统比基于自由线程的设计根安全,更迅速,更容易维护. QF提供了一个轻量级的软件总线,来集成软件部件--活动对象.
第三章 标准状态机标准状态机:通常的平面的有限状态机。
通常,状态机设计采用三种方式:
分支结构
状态(转换)表
状态设计模式
在以上基础上,获得一种优化的平面的有限状态机设计方式。
接口包括2大语义结构:外界输入集合;状态机
//定义外界输入:
如果输入比较复杂(带有特定的数据结构,回调函数)怎么办?enum
Signal{
CHAR_SIG, STAR_SIG, SLASH_SIG
};
//定义状态机:接口类型-类
class
Fsm{
public:
//定义子状态:接口类型-函数
typedef void (Fsm::*State)(unsigned const sig); void init() { dispatch定义(0); }//初始状态
void dispatch(int sig) { (this->*myState)(sig); }//定义输入分发
protected:
State myState;//转换后状态
void tran(State target) { myState=target; }//状态转换
public:
Fsm(State initial):myState(initial) { }
virtual ~Fsm() { }
}
Fsm包含了以下内容:上下文;输入处理。
但却是无状态,无输出?成员函数指针是C、c++实现状态机最快的机制。
这里展现了1种技术:
如何把类接口转换成函数接口?平面的状态机模型太过简单,为了便于对复杂问题建模,必须扩展到层次式模型。
第四章 层次式状态机(行为继承元模式)1个基于事件的异步设计应具备5个元素:
执行上下文,事件队列,事件处理,事件发送,定时服务。QP把层次式状态机的概念映射到了主流语言C,C++。
UML虽然支持状态嵌套概念,但也包含了许多其他次要概念。大而全的UML规范妨碍了小而有效的实现。
HSM着重于下列元素:
完全支持行为继承的层次式状态; 用状态进入和退出动作来实现有保证的初始化和清除; 支持状态可继承。行为继承元模式把自己限定为
被动事件处理器。不包括传统上的标准元素(理由:这些与OS密切相关;有些OS提供了完整的事件驱动环境)。
行为继承元模式的目的是提供类属事件处理器,使得可以使用任何事件排队和分发机制。
行为继承元模式的策略是提供足够但不多的真正基本元素,允许所有状态图特性的有效构建。
in "qep.h", v3.4.0:
typedef uint8_t
QSignal;struct QEvent { QSignal sig; uint8_t dynamic_;};class QHsm; // forward declaration
typedef void (*
QState)(QFsm *me, QEvent const *e);
class QFsm {protected: QState state_; public: virtual void init(QEvent const *e = (QEvent const *)0); virtual void dispatch(QEvent const *e);protected: QFsm(QState initial) : state_(initial) {} virtual ~QFsm(); QState getState(void) const { return state_; }};class QHsm; // forward declaration
typedef
QState (*
QHsmState)(
QHsm *me,
QEvent const *e);
class QHsm {protected: QState state_; public: virtual void init(QEvent const *e = (QEvent const *)0); virtual void dispatch(QEvent const *e); uint8_t isIn(QHsmState state);protected: QHsm(QState initial) : state_(initial) {} static QSTATE top(QHsm *me, QEvent const *e); QHsmState getState(void) const { return (QHsmState)state_; }};
事件:事件应归一化表示
QEvent设计为结构体,而不是类。
状态:由于状态对象要求存储和初始化的缺点,状态接口设计为方法指针,而不是类。这允许了FSM的直接扩展。是一大理念突破!
QState
进/出动作和初始转换 是状态专有的特性,在状态中它们被定义,与经过的转换路径无关。
状态转换 在源状态的上下文中执行转换动作(UML武断地规定离开源状态上到LCA,然后再执行转换动作)
top状态和初始伪状态 top状态唯一目的就是规定状态层次的根,以使得最高级状态处理器能返回top。
QHsm构造函数不执行初始伪状态中的初始转换,因为用户不能精确控制C++执行构造函数的定时。用户代码必须调用init()显式地出发初始转换。
优化的行为继承元模式的Hsm实现提供的只是状态机的事件处理器构件,故意忽略了时间排队和时间分发机制,这些也是理想的状态机必需的构件。本实现的事件处理器,能与任何事件队列,事件分发机制一起使用。
第八章 QF的设计嵌入式和实时这两个概念是有区别的.
与从桌面系统借来的传统解决方案相比,QF简化了实现.这些领域包括: 错误处理和异常; 内存管理; 传送事件; 初始化和清除; 事件管理.
异常处理:一个错误的安全感!
契约式设计 DBC
QF 应用了契约式设计方法学, 使用了断言.
DBC 的中心思想是--
将契约融入到代码中,并在其运行时生效.好处是:
自动捕获Bug; 文档代码化.理解契约最重要的一点是: 它们既不处理,也不防止bug,就像契约不会防止人们之间的欺骗一样
契约将每个被断言的不管多么良性的bug都转变成1个致命的错误.
处理bug时,最优先的考虑是要捕获它们,修正它们不在考虑范围之内.
DBC 对于嵌入式实时系统来说特别有价值,因为契约能够覆盖所有在其他领域中被要求作为异常条件处理的情形.
如果可以,请考虑从嵌入式软件中省去C++的异常处理机制(例如,EC++就有意不支持异常);
如果无法避免,就确保在异常可能造成任何损害之前捕获它们.
内存管理
嵌入式应用中,严格限制堆分配.
互斥和阻塞
对一个共享资源进行互斥访问的方法有:
禁止中断; 禁止任务切换; 用信号量锁定资源.
基于活动对象的系统的中的阻塞
通常,活动对象由于3种原因被阻塞:
1. 等待RTC步奏之间的新事件
2. 在1个RTC不走的中间等待其他活动对象
3. 等待遇其他活动对象无关的事件
第1种是正常的. 第2种是不好的观念,应尽量避免. 第3种有时候难以避免.
在基于活动对象的系统中由于互斥而产生的阻塞,就像是机器中的摩擦,会对机器造成破坏.
传送事件
动态事件分配
出版-订阅模型
组播事件
自动事件回收
活动对象内部状态机
事件队列
执行线程
初始化/清除时间管理第九章 量子框架的实现
QP/C++ Class List | Base class for derivation of application-level active object classes 应用级活动对象的基类 |
| Macro
to specify compiler-specific directive for placing a constant object in
ROM.Macro to specify compiler-specific directive for accessing a
constant object in ROM.Provides miscellaneous QEP services |
| Native Event Queue class QF事件队列类 |
| QEvent base class QF事件基类 |
| QF services QF基础服务(出版-订阅,。。。) |
| Structure representing a free block in the Native Memory Pool |
| Finite State Machine base class 平面式状态机 |
| Hierarchical State Machine base class 层次式状态机基类 |
| QK services QK核心服务 |
| Native memory pool class QF内存池管理类 |
| Priority Set useful for building various schedulers, but also useful as a general set of up to 64 elements of any kind |
| Priority Set useful for building various schedulers, but also useful as a general set of up to 8 elements of any kind |
| Quantum Spy logging facilities Log 设施 |
| Subscriber List class |
| Time Event class 事件时间类
|