簡體   English   中英

C++過濾管線

[英]C++ Filter Pipeline

我想為我的應用程序開發一個過濾器管道。 管道應該由任意數量的過濾器組成。

對於過濾器,我聲明了一個抽象基 class,如下所示:

struct AbstractFilter {
    virtual void execute(const std::string& message) = 0;
    virtual ~AbstractFilter() = default;
}

每個過濾器都應該從這個基礎 class 繼承並實現execute方法。 像這樣:

struct PrintMessage : public AbstractFilter {
    void execute(const std::string& message) override {
        std::cout << "Filter A " << message << '\n';
        //hand over message to next Filter

    }
}

struct Upper : public AbstractFilter {
    void execute(const std::string& message) override {
        std::string new_line;
        for (char c : line)
           new_line.push_back(std::toupper(c));
        //hand over message to next Filter
    }
}

struct WriteToFile : public AbstractFilter {
    void execute(const std::string& message) override {
        std::ofstream of{"test.txt"};
        of << message;
        of.close();
    }
}

編輯1:

消息應該從管道中的一個過濾器發送到下一個過濾器。 例如,如果管道是這樣的:

上 -- PrintMessage -- WriteToFile

消息應通過所有 3 個過濾器。 (例如,如果Upper完成了他的工作,則應該將消息發送到PrintMessage等等)

在上面的示例中,如果消息Hello World被發送到管道,則 output 應該是:

Console:
HELLO WORLD
test.txt:
HELLO WORLD

編輯2:

過濾器僅更改給定消息的內容。 類型沒有改變。 每個過濾器都應該使用例如字符串或給定的 class。 消息僅轉發給一位收件人。

我現在的問題是如何連接這些過濾器?

我的第一個猜測是使用Queues 所以每個過濾器都有一個InputOutput隊列。 為此,我認為每個過濾器都應該在它自己的Thread內運行,並在數據添加到他的Input隊列時得到通知。 (例如FilterA的Output隊列也是FilterB的Input隊列)

我的第二個猜測是使用責任鏈模式和boost::signals2所以 FilterB 例如連接到 FilterA 的信號。 FilterA 在完成工作后調用這些過濾器。

兩種解決方案哪個更靈活? 或者有沒有更好的方法來連接過濾器?

另一個問題是否也可以在一個線程內運行整個管道,以便我可以啟動多個管道? (在示例中,有 3 個 FilterA-FilterB-FilterD 管道啟動並運行?)

我認為 AbstractFilter 不是必需的,我建議使用 std::tuple 來定義管道:

std::tuple<FilterA, FilterB> pipeline1;
std::tuple<FilterA, FilterB, FilterC ... > pipeline2;

要通過管道運行消息(使用 c++17):

template<typename Pipeline>
void run_in_pipeline(const std::string& message, Pipeline& pipeline){
  std::apply([&message](auto&& ... filter) {
    (filter.execute(message), ...);
  }, pipeline);
}

如果您關心性能並且過濾器必須按順序執行,我不建議在單個管道上使用多線程或信號槽模式。 如果您正在處理多線程應用程序,請考慮在不同的線程上運行不同的管道

我會以這種方式進行:創建一個包含所有已實現版本的抽象過濾器的列表。 因此,按照您的示例,在閱讀輸入文件后,我將獲得一個列表:

[0]:Upper 
[1]:PrintMessage
[2]:WriteToFile

然后一個線程(如果您需要一次處理許多字符串,則為線程輪詢)在輸入隊列中等待一個字符串。 當池中出現新字符串時,線程在過濾器列表上循環,最后將結果發布到 output 隊列中。

如果你想並行運行它,你需要找到一種方法來保持輸入字符串 anche nelle stringhe di output 的順序。

我相信責任鏈模式更簡單,允許更簡潔的代碼和更大的靈活性。

您不需要第三方庫來實現它。
您所說的過濾器實際上是處理程序 所有處理程序都實現一個通用接口,定義一個可以命名為handle()的方法,甚至可以將 object 作為參數來共享 state。 每個處理程序都存儲一個指向下一個處理程序的指針。 它可能會或可能不會在其上調用該方法; 在后一種情況下,處理停止,它充當過濾器

如果其中一些需要其他的 output 作為輸入,則並行運行流水線階段會更復雜。 對於並行運行的不同管道,每個管道都將在自己的線程上運行,您可以使用隊列將輸入傳遞給它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM