gpt4 book ai didi

复杂的状态转换 : best practices

转载 作者:太空宇宙 更新时间:2023-11-03 23:25:25 26 4
gpt4 key购买 nike

我从事嵌入式工作,我有一些管理硬件的软件模块。这个模块有状态,状态转换很复杂:根据事件,模块可以从状态 A 到状态 B 或者可能到 C .但是,当它退出某个状态时,它应该对硬件执行一些操作,以使其也保持在正确的状态。

对于相当简单的模块,我只有几个这样的函数:

enum state_e {
MY_STATE__A,
MY_STATE__B,
};

static enum state_e _cur_state;

void state_on_off(enum state_e state, bool on)
{
switch (state){
case MY_STATE__A:
if (on){
//-- entering the state A
prepare_hardware_1(for_state_a);
prepare_hardware_2(for_state_a);
} else {
//-- exiting the state A
finalize_hardware_2(for_state_a);
finalize_hardware_1(for_state_a);
}
break;
case MY_STATE__B:
if (on){
//-- entering the state B
prepare_hardware_1(for_state_b);
prepare_hardware_2(for_state_b);
} else {
//-- exiting the state B
finalize_hardware_2(for_state_b);
finalize_hardware_1(for_state_b);
}
break;
}
}

void state_set(enum state_e new_state)
{
state_on_off(_cur_state, false);
_cur_state = new_state;
state_on_off(_cur_state, true);
}

显然,我们需要在 _state_on_off() 函数中保留所有状态的所有必要操作,当我们需要移动到另一个状态时,我们只需调用 _state_set(new_state) 并且状态转换顺利进行,与方向无关:执行所有需要的操作。

但它只适用于简单的情况。如果我们在状态 MY_STATE__BMY_STATE__C 之间有一些共同点,那么当状态从 MY_STATE__B 更改为 MY_STATE__C 时会怎样> 然后我们应该只执行缩短的破坏/构造?但是当我们进入其他状态时(例如,进入 MY_STATE__A),我们应该执行完全销毁。

想到的是子状态。所以我们有一个状态 MY_STATE__BC,以及像 MY_BC_SUBSTATE__BMY_BC_SUBSTATE__C 这样的子状态;当然我们有它自己的函数,比如 _state_bc_on_off()。即使这已经是一种痛苦,但想象一下更复杂的事情:它会变得很糟糕。

那么,此类事情的最佳实践是什么?

最佳答案

一个稍微更通用的状态机有

  • 原语——在特定硬件上执行特定操作的子例程
  • sequences -- 按特定顺序调用的一个或多个原语
  • transitions -- 以特定顺序执行的一个或多个序列

转换被编码在一个结构数组中。序列由switch语句选择,每个序列调用一个或多个原语。

#define stA    0x00000001  // bit mask for state A
#define stB 0x00000002 // bit mask for state B
#define stC 0x00000004 // bit mask for state C
#define stAny 0xffffffff // matches any state

enum { seqXtoY, seqError, seqEnterA, seqExitA, seqEnterB, seqExitB, seqEnableC, seqDisableC, seqEnd };

typedef struct
{
int oldState; // bit mask that represents one or more states that we're transitioning from
int newState; // bit mask that represents one or more states that we're transitioning to
int seqList[10]; // an array of sequences that need to be executed
}
stTransition;

static stTransition transition[] =
{
// transitions from state A to B or C
{ stA, stB, { seqExitA, seqXtoY, seqEnterB, seqEnd } },
{ stA, stC, { seqExitA, seqXtoY, seqEnableC, seqEnterB, seqEnd } },

// transitions from state B to A or C
{ stB, stA, { seqExitB, seqXtoY, seqEnterA, seqEnd } },
{ stB, stC, { seqXtoY, seqEnableC, seqEnd } },

// transitions from states C to A or B
{ stC, stA, { seqDisableC, seqExitB, seqXtoY, seqEnterA, seqEnd } },
{ stC, stB, { seqDisableC, seqXtoY, seqEnd } },

// any other transition (should never get here)
{ stAny, stAny, { seqError, seqEnd } }
};

static int currentState = stA;

void executeSequence( int sequence )
{
switch ( sequence )
{
case seqEnterA:
prepare_hardware_1(for_state_a);
prepare_hardware_2(for_state_a);
break;

case seqExitA:
finalize_hardware_2(for_state_a);
finalize_hardware_1(for_state_a);
break;

case seqEnterB:
prepare_hardware_1(for_state_b);
prepare_hardware_2(for_state_b);
break;

case seqExitB:
finalize_hardware_2(for_state_b);
finalize_hardware_1(for_state_b);
break;

case seqEnableC:
enable_hardware_3();
break;

case seqDisableC:
disable_hardware_3();
break;
}
}

void executeTransition( int newState )
{
if ( newState == currentState )
return;

// search the transition table to find the entry that matches the old and new state
stTransition *tptr;
for ( tptr = transition; tptr->seqList[0] != seqError; tptr++ )
if ( (tptr->oldState & currentState) && (tptr->newState & newState) )
break;

// execute the sequence list
int *seqptr;
for ( seqptr = tptr->seqList; *seqptr != seqEnd; seqptr++ )
{
if ( *seqptr == seqXtoY )
currentState = newState;
else if ( *seqptr == seqError )
printf( "The state table is missing the transition from %d to %d\n", currentState, newState );
else
executeSequence( *seqptr );
}

// if the seqList doesn't have an explicit update, then we update at the end
currentState = newState;
}

关于复杂的状态转换 : best practices,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28356569/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com