2016-03-26 25 views
1

我有一個C++字符分析函數,它被寫入在它自己的線程中運行。它的目的是在每次需要更多數據進行處理時進行阻止調用,並且在處理所有數據之前永遠不會返回。是這樣的:把一個無狀態的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 s跳回到其以前的位置。

任何人都可以提出一個更優雅,更少雜亂,也許不涉及轉到的替代方案嗎?例如,C++對於實現這些'有狀態返回'具有什麼其他用途?

+0

也許像setjmp/longjmp?除此之外,我認爲沒有固有的方式來保持這種模式。如果只有C++有monads ... –

+0

還有一個整潔的協程庫文件http://www.boost.org/doc/libs/1_53_0/libs/coroutine/doc/html/index.html –

回答

0

請勿使用static:這些幾乎都是變相的全局變量。

有一個涉及await關鍵字的微軟提議,使您的更改變得微不足道。但那還沒有到。

除了我們使用類成員狀態變量而不是靜態變量和operator()外,將該提議「機械」轉換爲當前C++代碼看起來像您的解決方案。他們也支持作文,但你不需要那樣。

您可以直接在void指針指針和goto中存儲標籤來替換開關維護。

可以完成從goto解決方案中的重構。在返回之間執行每次代碼運行,並首先將其放入lambda表達式中,然後放入方法中。這可能是困難的,不可能的或毫無意義的,但重構可能最終取代goto。你最終可能會得到一臺狀態機,它只比spagetti goto更容易理解。

真正乾淨的解決方案正在等待未來版本的C++中的協同程序;抱歉。你可能可以從今天看看人們如何實現協同程序的想法...

+0

我從來沒有聽說過C中的標籤指針,但這些看起來很有用。 (順便說一句,我開始認爲我之前'代碼'的整個原因是按照它的方式排列的,是因爲它不*類似於狀態機) – dwk

0

要生成有狀態的函數,請使用仿函數。這是帶有overloaded()運算符的類的對象。你在初始狀態下實例化這個對象,由構造函數設置,並且在調用Object()期間,調整狀態,如前所述,這個狀態保存在對象內部。

+0

這可能是一個整潔最終結果,但不回答我的問題,除非你只讀標題。問題是如何取得一個成熟的代碼塊並將其轉換爲最少修改的形式。 – dwk

相關問題