状态机的事件处理

The run-to-completion paradigm

状态机执行中对事件出现的处理遵循第13章定义的一般化语义。在创建时,状态机将执行它的初始化,其中它会执行一个由创建导致的初始的复合转变,此后它进入一个等待点。在状态机行为中,等待点代表了稳定的状态配置。状态机维持当前状态直到事件池中一个存储的事件被派发。这个事件被计算并且,如果它与状态机的一个有效地触发器相匹配并且至少有一个使能的转变可以被该事件出现所触发,那么状态机执行一步。一步涉及执行一个复合转变并且终止在一个稳定的状态配置上(即下一个等待点)。这个过程重复执行直到状态机执行完它的行为或者它被某些外部代理异步终止掉。

状态机可以对第13章描述的任意事件类型,以及完成事件做出响应。

注意. 按照上面的解释,完成事件具有高优先级,优先于事件池中待定事件出现的派发。

事件出现一次一个地被状态机执行所检测、派发和处理。

注意. 事件派发的顺序未定义,允许不同的调度算法。

这个过程被称为run-to-completion paradigm,相应的状态机步骤被称作run-to-completion step。Run-to-completion意味着在没有异常或异步销毁的情况下,待定的事件出现只在前一个出现被完全处理完毕并且到达一个稳定的状态配置后才派发。也就是说,在状态机执行忙于处理之前一个的时候,事件出现不会被派发。选择这种行为范式是为了避免并发冲突(可能在状态机试图对多个并发或重叠事件做出响应时出现)带来的复杂性。

如果一个事件出现被检测和派发,它可能导致一个或多个转变变得使能可以被触发。如果没有转变使能并且相应的事件类型不在当前活跃状态配置的任意deferrableTriggers列表中,那么这个被派发的事件出现被丢弃并且该Run-to-completion步骤平凡地结束。

由于正交区域的出现,有可能多条转变(位于不同的区域)被相同的事件出现所触发。这些转变的执行顺序没有定义。当前活跃状态配置中的每个不含有内嵌正交区域的正交区域(即,最底层的区域)可以作为当前事件出现的结果触发至多一条转变。当所有正交区域都执行完转变,当前的事件出现被完全消费,Run-to-completion步骤结束。

上面提到,有可能在某个区域中多个相互排斥的转变都可以被相同这个相同的事件出现所触发,此时,只能选择执行一个,选择哪个由下面的算法决定。

在一个转变中,可能做执行一组动作行为。如果这样的一个行为包括对另一个对象有一个同步的调用执行一个状态机,那么这个转变步骤要在被调用对象对象方法完成它的Run-to-completion步骤后才能结束。

Run-to-completion可以以不同的方式实现。对于主动类,它可能被实现为自有线程内的事件循环,从池中读事件出现。对于被动类可以用一个监视器(monitor)来实现。

实现注意. Run-to-completion经常被误解为执行中的状态机不能被中断,怕会导致在一些时间敏感型系统中的优先级反转问题。然而,情况不是这样的;在一个给定的实现中,执行状态机步骤的线程可以被挂起,这允许高优先级的线程运行,并且,当它再次获得处理机时间时,它又可以继续它的执行直到事件处理完成。

使能的转变

转变是使能的当且仅当:

  • 它的所有状态处于活跃状态配置中。
  • 转变的至少一个触发器的事件与被派发的事件出现的事件类型匹配。如果是信号事件,那么任何与触发器中规定的类型相同或兼容的出现都可以匹配。如果其中的一个触发器是用于AnyReceiveEvent的,那么只要相同的转变上没有其它信号或CallEvent触发器或者没有与具有该AnyReceiveEvent触发器的转变有相同源顶点的其它转变,那么任意的一个信号或CallEvent都可以满足该触发器(参见13.3.1)。
  • 如果至少存在一个完整的从源状态配置到或者是目标状态配置或者是一个动态的choice伪状态(其中所有的guard为真,没有guards的转变也被视为真)。

由于相同的事件出现可能使得多个转变使能,变为使能只是转变执行的必要条件而非充分条件。

冲突的转变

在一个状态机中可能有多个转变可以使能。如果出现了类似情况,那么这些转变可能是互相冲突的。举个例子,考虑两个源自相同状态的转变,它们都被相同的事件所触发,但是具有不同的guards。如果那个事件发生并且两个guard条件都为真,那么至多只能有一个转变可以在一个给定的run-to-completion步骤中执行。

如果两个转变都离开相同的状态,那么就说它们是冲突的,或者再准确一些,当它们所离开的状态集合的交集不空时。只有位于相互正交区域内的转变可以同时执行。这个约束保障了执行转变集所导致的新的活跃状态配置是良构的。

状态中一个internal转变只与那些导致离开该状态的转变冲突。

执行优先级

在转变冲突的场景下,选择哪个转变执行(部分)基于一个隐含优先级。这些优先级可以解决一些但不是全部的转变冲突,因为它们之定义了一个偏序。互相冲突的转变的优先级基于它们在状态层级中的相对位置。定义上,源自子状态的转变比源自包更高层状态的冲突转变具有更高的优先级。

转变的优先级基于它的状态来定义。复合转变链中的转变的优先级基于具有最深层状态的转变的优先级来定义。

通常,如果转变t1的源状态是s1,t2的是s2,那么:

  • 如果s1是s2的子状态,那么t1的优先级高于t2。
  • 如果s1和s2并不在相同的装配配置中,那么它们之间没有优先级区别。
转变选择算法

当前状态配置中的要执行的转变需要满足如下条件:

  • 转变是使能的。
  • 不存在冲突转变。
  • 没有更高优先级的转变。

这可以通过一个对活跃状态配置进行直接遍历的贪心选择算法来实现。活跃状态配置中的状态遍历时从最里层的简单状态开始的,逐步向外扩展。对于给定层次上的每个状态,所有源自该状态的转变都被评估以决定是否使能。这种遍历保障了优先级选择不会被违反。唯一有点难度的问题就是解决所有层次上跨正交状态的转变冲突。一旦某个区域内部的元素的一个转变执行,那么就终止在每个正交状态中的搜索来来解决这个问题。

转变执行序列

除了internallocal之外的每个转变,都导致离开一个源状态,进入目标状态。这两个状态,可能是组合的,被分别指示为一个转变的main sourcemain target

主要源是包含源状态的区域的一个直接子状态,主要目标是包含目标状态的区域的一个子状态。

注意. 在相同直接所属的组合状态中,不允许转变从一个区域到另一区域。

一旦转变使能并被选中执行,那么会按序执行如下的步骤:

  1. 从它的主要源状态开始,按照之前介绍的状态离开规则,包含主要源状态的状态被离开(或者如果注意源状态是内嵌的,那么组合状态退出)。
  2. 状态离出一直持续到到达一个既包含主要源又包含主要目标状态的区域。该区域称为主要源和主要目标状态的最小公共祖先。在这个点上,连接源状态子配置到目标状态子配置的转变的effect行为被执行(这里的子配置指的是最小公共祖先区域内包含的完整状态配置的子集)。
  3. 进入包含主要目标状态的状态的配置,从包含主要目标状态的最小公共区域的最外层状态开始。行为的执行按照之前描述的状态进入规则。

该转变执行算法由图14.2中的状态机实例来说明。此例中,当状态机处于状态S11(主要源)且事件sig要被派发时,如下的动作序列会被执行:

xS11; t1; xS1; t2; eT1; eT11; t3; eT111

图14.2 Compound transition example

results matching ""

    No results matching ""