79 lines
3.1 KiB
C++
79 lines
3.1 KiB
C++
// Example 05 — Error Handling & Diagnostics
|
|
//
|
|
// Demonstrates observable failure modes and the diagnostics system:
|
|
//
|
|
// 1. ChannelOverflowError — a fast producer saturates a slow consumer.
|
|
// When the channel is full, push() throws ChannelOverflowError.
|
|
// The node's run_loop catches it and prints to stderr.
|
|
// Channel statistics (overflows, peak fill) accumulate for the report.
|
|
//
|
|
// 2. Custom diagnostics handler — instead of the default periodic table,
|
|
// install a handler that surfaces only the metrics you care about.
|
|
//
|
|
// 3. net.print_diagnostics() — print a full report at any time.
|
|
//
|
|
// Pipeline: [producer] --int--> [slow_consumer]
|
|
|
|
#include <kpn/kpn.hpp>
|
|
#include <chrono>
|
|
#include <iostream>
|
|
#include <thread>
|
|
|
|
// ── Node functions ────────────────────────────────────────────────────────────
|
|
|
|
// Produces at ~100/s — faster than the consumer can keep up (50 ms each)
|
|
static int producer() {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
static int n = 0;
|
|
return ++n;
|
|
}
|
|
|
|
// Slow consumer: 50 ms per item — will cause channel to fill and overflow
|
|
static void slow_consumer(int x) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
std::cout << "[consumed] " << x << '\n';
|
|
}
|
|
|
|
// ── main ──────────────────────────────────────────────────────────────────────
|
|
|
|
int main() {
|
|
using namespace kpn;
|
|
|
|
// Capacity=4: fills up quickly when producer outpaces consumer 5:1
|
|
auto prod = make_node<producer> (out<"v">{}, /*capacity=*/4);
|
|
auto cons = make_node<slow_consumer> (in<"v">{}, /*capacity=*/4);
|
|
|
|
Network net;
|
|
|
|
// Custom diagnostics handler — fires on the watchdog interval.
|
|
// Print a concise one-liner rather than the full table.
|
|
net.set_diagnostics_handler([](const std::vector<NodeSnapshot>& nodes,
|
|
const std::vector<ChannelSnapshot>& channels) {
|
|
std::cout << "[diag] ";
|
|
for (auto& n : nodes)
|
|
std::cout << n.name << "=" << n.throughput_fps << "fps ";
|
|
for (auto& c : channels)
|
|
std::cout << "channel fill=" << static_cast<int>(c.fill_pct()) << "% "
|
|
<< "overflows=" << c.overflows;
|
|
std::cout << '\n';
|
|
});
|
|
|
|
net.set_watchdog_interval(std::chrono::milliseconds(200));
|
|
|
|
net.add("prod", prod)
|
|
.add("cons", cons)
|
|
.connect("prod", prod.template output<"v">(), "cons", cons.template input<"v">())
|
|
.build();
|
|
|
|
std::cout << "producer: 10ms/item, consumer: 50ms/item, capacity=4\n"
|
|
<< "Overflow messages appear on stderr; diagnostics on stdout.\n\n";
|
|
|
|
net.start();
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(800));
|
|
net.stop();
|
|
|
|
// Full report after shutdown — overflow and drop counts are preserved
|
|
std::cout << '\n';
|
|
net.print_diagnostics();
|
|
}
|