2011-08-06 73 views
3

我在學習boost :: statechart。提升狀態圖轉換參數

我想製作一個加載文件的小應用程序。

// -------------------------------- 
// |        | 
// |   O  Project  | 
// |   |     | 
// |   v     | 
// | ---------------------------- | 
// | |       | | 
// | |   Unloaded   | | 
// | ---------------------------- | 
// | |   ^   | 
// | | EvLoad  | EvUnload  |<-----O 
// | v    |    | 
// | ---------------------------- | 
// | |       | | 
// | |   Loaded    | | 
// | ---------------------------- | 
// |   | ^    | 
// |   | | EvLoad   | 
// |   -----    | 
// -------------------------------- 

但我該如何將參數傳輸到狀態,例如,一個文件名? 如果我的名店內EvLoad我可以很容易地訪問它的狀態反應

struct Loaded : sc::simple_state< Loaded, Project> 
{ 
    typedef sc::custom_reaction<EvLoad> reactions; 
    sc::result react(const EvLoad & e) 
    { 
     //load file e.path() 
     ... 
     return discard_event(); 
    } 
} 

但是,當我在空載狀態下是那麼我調用的加載構造,我不能傳遞參數到它。我提出的唯一解決方法是在轉換之前重新發布事件,但這對我來說看起來有點骯髒。

struct Unloaded : sc::simple_state< Unloaded, Project > 
{ 
    typedef sc::custom_reaction<EvLoad> reactions; 
    sc::result react(const EvLoad & e) 
    { 
     post_event(e); //workaround to pass the event to the loaded state 
     return transit<Loaded>(); 
    } 
}; 

有沒有更好的選擇?

回答

4

我在Google搜索過程中找到了this link,之後我在下面輸入了我的建議,說明您已經在做什麼(發佈內部事件或重新發布事件和數據)是實現它的方法。這是來自Boost狀態圖的作者,那麼誰來爭論呢? :)

我的另一種建議是,如果任何數據存在於「項目」級別,一旦加載,則加載的文件名將是「項目」級別的FSM狀態信息的一部分,而不是「已加載」狀態。

您可以使文件名成爲EvLoad事件/構造函數的參數,對轉換執行自定義操作並存儲在「項目」上下文中加載的文件名。我認爲這更符合狀態圖的概念。

所以這樣的事情(雖然我沒有測試過),顯然你會清理封裝比這更好的成員:

struct EvLoad: sc::event<EvLoad> 
{ 
    std::string filename; 

    EvLoad(const std::string& fn) : filename(fn) {} 
}; 

struct EvUnload: sc::event<EvUnload> 

struct Project : sc::state_machine<Project, Unloaded> 
{ 
    std::string filename; 

    void LoadFile(const EvLoad& e) 
    { 
     // Load file 
     filename = e.filename; 
    } 

    void UnloadFile(const EvUnload& e) 
    { 
     filename.clear(); 
     // Unload file data 
    } 
}; 

struct Unloaded : sc::simple_state<Unloaded, Project> 
{ 
    typedef sc::transition<EvLoad, Loaded, Project, &Project::LoadFile> reactions; 
}; 

struct Loaded : sc::simple_state<Loaded, Project> 
{ 
    typdef mpl::list< 
     sc::transition<EvLoad, Loaded, Project, &Project::LoadFile>, 
     sc::transition<EvUnload, Unloaded> 
    > reactions; 
}; 

當你去加載文件驅動statemachine與調用,如project.process_event(EvLoad(文件名));

或者,您可以將文件名存儲在「項目」狀態,並使用上下文()。從加載狀態的文件名訪問它。

9

我們使用triggering_event方法來拉動觸發事件,然後將數據作爲成員變量附加到觸發事件。它節省了大量的編碼工作,使我們不必生成自定義反應或將轉換變量附加到狀態圖(我見過的兩種常見方法)。

+0

當我明白這一點時,我的生活變得更加容易。 +1 – odinthenerd

+0

你有沒有可以分享的例子? – ksl