首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >子状态机如何将控制权放弃给父状态机?

子状态机如何将控制权放弃给父状态机?
EN

Software Engineering用户
提问于 2012-02-09 18:35:13
回答 3查看 2K关注 0票数 10

我的顶级状态机有一些状态和边缘。我将把这称为父状态机。

代码语言:javascript
复制
A ----> B ----> C

父状态机中的任何状态也可以是状态机。我给这些孩子打电话叫国家机器。

代码语言:javascript
复制
           ___________
         /            \
A ----> |  B0->B1->B2  | ----> C
         \____________/

如果父状态机从A转换到B,则B的状态机接管。一旦B完成运行,它应该如何将控制放弃给父状态机并转换到状态C?你使用哪种设计模式?

如果您想知道,我在父状态机中有子状态机,因为我的确切项目非常复杂,很自然地封装子状态的内部工作。

EN

回答 3

Software Engineering用户

回答已采纳

发布于 2012-02-09 20:07:17

每个状态机都有某种事件处理程序和触发这些事件的方法。该处理程序将现有状态和事件类型作为输入,选择新状态,并可选择运行一些副作用代码。

本质上,在状态B中,您的主事件处理程序将不识别的任何事件转发给B的S事件处理程序,并保持在状态B中。当B希望转换到C时,它会将适当的事件发布到主事件处理程序。

票数 6
EN

Software Engineering用户

发布于 2012-02-09 19:51:13

你读过Taoup的这段吗?完成此任务有几种不同的方法,但其中许多方法取决于您如何拆分状态机。它们是分开的过程吗?线?物品?

找出你是如何构建它们的,看看它们是否有一种规范的沟通方式。如果一个系统不存在,那么您的系统设计可能是错误的。

对我来说,我会观察不同的过程,把stdin和stdout连接在一起。子状态机然后变得独立,在stdin上操作,在stdout上输出。它成为父状态机的工作,启动子进程,连接管道,然后转储数据并等待结果。所有这些事情都是用现代语言做的,所以应该很容易做到。

票数 2
EN

Software Engineering用户

发布于 2012-02-09 20:31:18

分离这两台状态机并使用它们之间的消息传递。因此,状态机1将从A B C开始,在B状态下它检查状态机2的当前结果。如果输出已经改变,那么状态机1可以解释它,状态机2不需要知道状态机1实际上是如何工作的。类似于:

代码语言:javascript
复制
typedef struct StateMachine {
  void(*Update)(); // function to update the state machine
  int Data;        // generic temp holder to survive state contexts
  int State;       // current state of our state machine
  int *Message;    // pointer to a shared integer for message passing
};

int main(void) {
  int Message = 0;
  /* NewStateMachine would malloc the struct, pass in the int reference
   * and function pointer as well as add it to a circularly linked list */
  NewStateMachine(&Message, MainLoop);
  NewStateMachine(&Message, MinorLoop);
  StateMachine *Current = StateMachine_CLL.First;

  for(;;) {
    Current->Update(Current); /* Update the current state machine */
    Current = Current->Next;  /* And the advance to the next one */
  }
}

void MainLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    CloseCoolantTank(1); /* safe to call if valve already closed */
    CloseCoolantTank(2); /* safe to call if valve already closed */
    this.State = 1;
    break;
  case 1:
    /* we have a message, do something */
    if(*this.Message) this.State = 2;          
    /* otherwise stall at this state until we get a message */
    else this.State = 1;          
    break;
  case 2:
    if(*this.Message == 1) this.State = 3;      /* warm */
    else if(*this.Message == 2) this.State = 4; /* hot! */
    else this.State = 0;                        /* cooled down, shut off valves */
    this.Message = 0;                           /* clear the message */
    break;
  case 3:
    OpenCoolantTank(1); /* opens the valve, safe to call if already open */
    this.State = 2;     /* recheck for new message */
    break;
  case 4:
    OpenCoolantTank(2); /* opens the valve, safe to call if already open */
    this.State = 3;     /* also open coolant tank 1 for extra cooling */
    break;
  }
}

/* Monitor temperature and send messages on overheat */
void MinorLoop(StateMachine *this) {
  switch(this.State) {
  case 0:
    this.Data = ReadADCValue();
    this.State = 1;
    break;
  case 1:
    if(this.Data > 150) *this.Message = 2;
    else if(this.Data > 100) *this.Message = 1;
    this.State = 0;
    break;
  }
}
票数 2
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/134252

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档