// Example 02 — Named Ports // // A three-stage text pipeline where port names carry semantic meaning: // // [tokenise] --"words"--> [count_words] --"count"--> [report] // --"words"--> [report] // // Named ports let the connect() call read like documentation: // connect("tok", tok.output<"words">(), "cnt", cnt.input<"words">()) // A typo in the name is a compile-time error, not a runtime surprise. #include #include #include #include #include #include #include #include // ── Node functions ──────────────────────────────────────────────────────────── static int sentence_index = 0; static std::vector tokenise() { static const char* sentences[] = { "the quick brown fox jumps over the lazy dog", "kahn process networks are a model of concurrent computation", "each node runs in its own thread communicating via channels", "named ports catch wiring mistakes at compile time", }; std::istringstream ss(sentences[sentence_index++ % 4]); std::vector words; std::string w; while (ss >> w) words.push_back(w); std::this_thread::sleep_for(std::chrono::milliseconds(50)); return words; } // Returns (word_count, original_words) — two outputs via tuple static std::tuple> count_words(std::vector words) { return {static_cast(words.size()), std::move(words)}; } static void report(int count, std::vector words) { std::cout << "[" << count << " words] "; for (auto& w : words) std::cout << w << ' '; std::cout << '\n'; } // ── main ────────────────────────────────────────────────────────────────────── int main() { using namespace kpn; // --8<-- [start:named_port_creation] // tokenise: no inputs, one named output "words" auto tok = make_node(out<"words">{}, 4); // count_words: named input "words", named outputs "count" and "words" auto cnt = make_node(in<"words">{}, out<"count", "words">{}, 4); // report: two named inputs auto snk = make_node(in<"count", "words">{}, 4); // --8<-- [end:named_port_creation] // --8<-- [start:named_port_network] Network net; net.add("tok", tok) .add("cnt", cnt) .add("snk", snk) .connect("tok", tok.template output<"words">(), "cnt", cnt.template input<"words">()) .connect("cnt", cnt.template output<"count">(), "snk", snk.template input<"count">()) .connect("cnt", cnt.template output<"words">(), "snk", snk.template input<"words">()) .build(); net.start(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); net.stop(); // --8<-- [end:named_port_network] }