- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我从事嵌入式工作,我有一些管理硬件的软件模块。这个模块有状态,状态转换很复杂:根据事件,模块可以从状态 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__B
和 MY_STATE__C
之间有一些共同点,那么当状态从 MY_STATE__B
更改为 MY_STATE__C
时会怎样> 然后我们应该只执行缩短的破坏/构造?但是当我们进入其他状态时(例如,进入 MY_STATE__A
),我们应该执行完全销毁。
想到的是子状态。所以我们有一个状态 MY_STATE__BC
,以及像 MY_BC_SUBSTATE__B
和 MY_BC_SUBSTATE__C
这样的子状态;当然我们有它自己的函数,比如 _state_bc_on_off()
。即使这已经是一种痛苦,但想象一下更复杂的事情:它会变得很糟糕。
那么,此类事情的最佳实践是什么?
最佳答案
一个稍微更通用的状态机有
转换被编码在一个结构数组中。序列由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/
上下文 我有一个日间 TUMBLINGWINDOW(类似于下面所示的) SELECT DATEADD(day, -1, System.Timestamp()) AS WindowStart
因此,我正在开发一个非常小的 Web 组件,以作为更大的设计系统的一部分。 我对网络组件的使用有点陌生,但我知道这个特定的网络组件可以在一个布局中使用很多很多次。 此 Web 组件控制在传递给它的任何
我刚刚开发了一个 Android 应用程序(minSdkVersion 23/targetSdkVersion 29),可以连接到 BluetoothLE 设备以定期获取数据。 现在,在 MainAc
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improve
我一直在阅读有关 Airplay SDK 和 Dragonfire SDK 的内容。这些是在没有 Mac 的情况下进行 iphone 开发的合法选择吗?大家有更好的解决办法吗? 最佳答案 由于签名等原
我正在考虑使用 DTO 而不是传递我的域对象。我在这里和其他地方都读过几篇文章,我知道有几种方法可以完成这项工作。 如果我总共只有大约 10 个域类,并且考虑到我想在我的 View (WPF 前端)中
我的问题是,如果我有一个列表 list = [1,2,3,4,5,6,7] 如果我想知道这个列表中元素的数量,是len(list) 或 list.count 更好的选择?还是 .count 仅适用于来
我想知道 Django Rest Framework 的最佳实践。我一直通过每个用户使用不同的序列化程序(员工、帐户所有者、其他人)和 HTTP 方法来限制更改帐户上某些属性的访问权限,但我觉得这太不
我有数百个用于测试组件的脚本。这些脚本中的每一个都包含一组下标和单独的记录。 下标可以在多个 TC_Level 脚本中使用,甚至可以在其他下标中使用。 每个脚本都有一个唯一的名称。 例子: TC_1
我正在建立一个以两种语言提供产品信息的网站:英文和中文。 每个产品必须有英文名称,也可以有中文名称。 每次请求产品页面时,request检查对象以确定产品名称应该以英文还是中文显示。在后一种情况下,如
场景:应用程序具有可以启用某些优化的算法。默认情况下,有些是打开的,有些是关闭的。在 Java 中是否有一种方便的方法来实现某种全局属性系统? 要求: 必须很容易两次使用不同的设置运行程序的多个实例
我从事嵌入式工作,我有一些管理硬件的软件模块。这个模块有状态,状态转换很复杂:根据事件,模块可以从状态 A 到状态 B 或者可能到 C .但是,当它退出某个状态时,它应该对硬件执行一些操作,以使其也保
我有一个免费网站,可以流式传输实时股票期权数据。我想让用户制作并保存他们自己的 JavaScript 可调用工具来解释选项数据。用户可以调用这些自定义工具来帮助他们自己做出有关期权的买卖决定。 但对于
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 2 年前。 社区在 6 个
我不是 DBA,我不知道什么是最好的解决方案。我有两个表, Custumers Table CustomerId (primary key, identity) ... 和 Suppliers Tab
关闭。这个问题是opinion-based .它目前不接受答案。 想改善这个问题吗?更新问题,以便可以通过 editing this post 用事实和引文回答问题. 7年前关闭。 Improve t
我一直在阅读关于版本控制主题的所有问题,但我认为我没有找到一个看起来像我自己的场景。 场景是: 我们有一个中型/大型 Web 应用程序,它有(至少应该有)一个部署到所有客户端的核心。当我们向客户演示应
我希望根据继承来组织一些项目,目的是确定哪些项目是连接最密集的父项,并且还只是看到形成的连接。 通常这将通过拓扑排序来完成,但我的图有循环。是否有类似“尽力而为”拓扑排序的东西,它可以尝试根据连接数或
以下在 JQuery 中附加事件处理程序的方法有什么区别? (function () { var $body = $("body"); $('button').click(functi
我是一名优秀的程序员,十分优秀!