将无状态C ++函数内部转换为有状态函数

时间:2016-03-26 09:34:55

标签: c++ algorithm refactoring

我有一个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...
    }
}

在这个阻塞调用输入的实例中,函数会被乱七八糟,在多种不同的场景下,这些调用被不同地解释。

我需要将功能彻底改变。我没有一个单独的单片函数来等待输入,而是需要一个可以同步调用的函数,以便在新数据可用时对其进行处理。这意味着解析器代码需要从无状态变为记忆其状态。我需要尽可能快地修改代码。

我的初步想法是修改功能如下:

  1. 用静态变量替换局部变量(因此函数保持状态)

  2. 使用return语句替换阻塞调用,之后是“当前代码位置”变量的赋值。

  3. 当新输入可用时,请使用新数据再次调用该功能。

  4. 该函数的开头使用switch()和一堆goto来跳回到之前的位置。

  5. 任何人都可以建议一个更优雅,更少杂乱,也许不涉及goto的替代方案吗?例如,C ++是否还有其他任何远程用于实现这些“状态返回”的东西?

2 个答案:

答案 0 :(得分:0)

要创建有状态函数,请使用仿函数。这是具有重载()运算符的类的对象。您可以在构造函数设置的初始状态下实例化此对象,并在调用Object()期间调整状态,如上所述,该状态保留在对象内部。

答案 1 :(得分:0)

不要使用static:这些几乎是伪装的全局变量。

有一个微软的提案涉及await关键字,使您的更改变得微不足道。但现在还没有。

该提议对当前C ++代码的“机械”转换看起来像您的解决方案,除了我们创建类成员状态变量,而不是静态状态变量和operator()。它们也支持组合,但你不需要它。

您可以将标签直接存储在void指针指针和goto中来替换开关维护。

可以完成goto解决方案的重构。在返回之间进行每次代码运行并将其放在lambda中,然后放入方法中。它可能很难或不可能或毫无意义,但重构最终可能取代了。你最终可能会得到一台状态机,这只比spagetti goto更容易理解。

真正干净的解决方案正在等待未来某个版本的C ++中的协同程序;抱歉。您可以通过研究人们今天如何实现协同程序来获取想法......