[英]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
。 所以每個過濾器都有一個Input
和Output
隊列。 為此,我認為每個過濾器都應該在它自己的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.