@@ -1,3 +1,118 @@
|
||||
// Example 04 — Storage Policy
|
||||
//
|
||||
// Demonstrates how KPN++ chooses between by-value and shared_ptr storage
|
||||
// inside channels depending on the type.
|
||||
//
|
||||
// Small trivially-copyable types (int, double, etc.) are stored by value.
|
||||
// Large or non-trivially-copyable types are stored as shared_ptr<const T>
|
||||
// — zero copies even across multiple downstream consumers.
|
||||
//
|
||||
// This example also shows how to override the policy for a specific type
|
||||
// with a template specialisation.
|
||||
//
|
||||
// [produce_frame] --Frame--> [process_frame] --Frame--> [consume_frame]
|
||||
// [produce_small] --int----> [double_it] --int----> [print_int]
|
||||
|
||||
#include <kpn/kpn.hpp>
|
||||
// TODO: implement example
|
||||
int main() { return 0; }
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
// ── Types ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
// Large frame type — will be stored as shared_ptr<const Frame> by default
|
||||
struct Frame {
|
||||
std::array<uint8_t, 4096> pixels{};
|
||||
int id = 0;
|
||||
};
|
||||
|
||||
// A small struct we force to be stored by value via policy specialisation
|
||||
struct Tag {
|
||||
int value = 0;
|
||||
};
|
||||
|
||||
// Override: store Tag by value despite being a struct
|
||||
// (it's trivially copyable and small — this just makes the policy explicit)
|
||||
template<>
|
||||
struct kpn::channel_storage_policy<Tag> {
|
||||
static constexpr bool by_value = true;
|
||||
};
|
||||
|
||||
// ── Node functions ────────────────────────────────────────────────────────────
|
||||
|
||||
static int frame_id = 0;
|
||||
static int tag_id = 0;
|
||||
|
||||
static Frame produce_frame() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
Frame f;
|
||||
f.id = frame_id++;
|
||||
f.pixels.fill(static_cast<uint8_t>(f.id & 0xFF));
|
||||
return f;
|
||||
}
|
||||
|
||||
static Frame process_frame(Frame f) {
|
||||
// Simulate some work
|
||||
for (auto& p : f.pixels) p = static_cast<uint8_t>(255 - p);
|
||||
return f;
|
||||
}
|
||||
|
||||
static void consume_frame(Frame f) {
|
||||
std::cout << "[frame] id=" << f.id
|
||||
<< " first_px=" << static_cast<int>(f.pixels[0])
|
||||
<< " storage=shared_ptr (sizeof Frame = " << sizeof(Frame) << " B)\n";
|
||||
}
|
||||
|
||||
static Tag produce_tag() {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
return {tag_id++};
|
||||
}
|
||||
|
||||
static Tag double_tag(Tag t) { return {t.value * 2}; }
|
||||
|
||||
static void print_tag(Tag t) {
|
||||
std::cout << "[tag] value=" << t.value
|
||||
<< " storage=by_value (sizeof Tag = " << sizeof(Tag) << " B)\n";
|
||||
}
|
||||
|
||||
// ── main ──────────────────────────────────────────────────────────────────────
|
||||
|
||||
int main() {
|
||||
using namespace kpn;
|
||||
|
||||
// Verify storage decisions at compile time
|
||||
static_assert(!channel_storage_policy<Frame>::by_value,
|
||||
"Frame should use shared_ptr storage");
|
||||
static_assert(channel_storage_policy<Tag>::by_value,
|
||||
"Tag should use by_value storage (via specialisation)");
|
||||
static_assert(channel_storage_policy<int>::by_value,
|
||||
"int should use by_value storage");
|
||||
|
||||
auto prod_f = make_node<produce_frame> (out<"frame">{}, 4);
|
||||
auto proc_f = make_node<process_frame> (in<"frame">{}, out<"frame">{}, 4);
|
||||
auto cons_f = make_node<consume_frame> (in<"frame">{}, 4);
|
||||
|
||||
auto prod_t = make_node<produce_tag> (out<"tag">{}, 4);
|
||||
auto dbl_t = make_node<double_tag> (in<"tag">{}, out<"tag">{}, 4);
|
||||
auto print_t = make_node<print_tag> (in<"tag">{}, 4);
|
||||
|
||||
Network net;
|
||||
net.add("prod_f", prod_f)
|
||||
.add("proc_f", proc_f)
|
||||
.add("cons_f", cons_f)
|
||||
.add("prod_t", prod_t)
|
||||
.add("dbl_t", dbl_t)
|
||||
.add("print_t", print_t)
|
||||
.connect("prod_f", prod_f.template output<"frame">(), "proc_f", proc_f.template input<"frame">())
|
||||
.connect("proc_f", proc_f.template output<"frame">(), "cons_f", cons_f.template input<"frame">())
|
||||
.connect("prod_t", prod_t.template output<"tag">(), "dbl_t", dbl_t.template input<"tag">())
|
||||
.connect("dbl_t", dbl_t.template output<"tag">(), "print_t", print_t.template input<"tag">())
|
||||
.build();
|
||||
|
||||
net.start();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(400));
|
||||
net.stop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user