我有一个C ++字符解析函数,它被编写为在自己的线程中运行。它旨在每次需要处理更多数据时进行阻塞调用,并且在处理完所有数据之前永远不会返回。像这样:
void runParser() {
while(true /*returns only when EOF encountered*/) {
//...
c = getNext(); //blocking call
//...
//...
c = getNext(); //blocking call
//...
//...
c = getNext(); //blocking call
//...
//...
//...
c = getNext(); //blocking call
//...
//...
c = getNext(); //blocking call
//...
//...50 more lines of code...
}
}
在这个阻塞调用输入的实例中,函数会被乱七八糟,在多种不同的场景下,这些调用被不同地解释。
我需要将功能彻底改变。我没有一个单独的单片函数来等待输入,而是需要一个可以同步调用的函数,以便在新数据可用时对其进行处理。这意味着解析器代码需要从无状态变为记忆其状态。我需要尽可能快地修改代码。
我的初步想法是修改功能如下:
用静态变量替换局部变量(因此函数保持状态)
使用return语句替换阻塞调用,之后是“当前代码位置”变量的赋值。
当新输入可用时,请使用新数据再次调用该功能。
该函数的开头使用switch()
和一堆goto
来跳回到之前的位置。
任何人都可以建议一个更优雅,更少杂乱,也许不涉及goto的替代方案吗?例如,C ++是否还有其他任何远程用于实现这些“状态返回”的东西?
答案 0 :(得分:0)
要创建有状态函数,请使用仿函数。这是具有重载()运算符的类的对象。您可以在构造函数设置的初始状态下实例化此对象,并在调用Object()期间调整状态,如上所述,该状态保留在对象内部。
答案 1 :(得分:0)
不要使用static
:这些几乎是伪装的全局变量。
有一个微软的提案涉及await关键字,使您的更改变得微不足道。但现在还没有。
该提议对当前C ++代码的“机械”转换看起来像您的解决方案,除了我们创建类成员状态变量,而不是静态状态变量和operator()。它们也支持组合,但你不需要它。
您可以将标签直接存储在void指针指针和goto中来替换开关维护。
可以完成goto解决方案的重构。在返回之间进行每次代码运行并将其放在lambda中,然后放入方法中。它可能很难或不可能或毫无意义,但重构最终可能取代了。你最终可能会得到一台状态机,这只比spagetti goto更容易理解。
真正干净的解决方案正在等待未来某个版本的C ++中的协同程序;抱歉。您可以通过研究人们今天如何实现协同程序来获取想法......