KPN/include/kpn/node.hpp
2026-05-12 21:23:33 +02:00

128 lines
5.1 KiB
C++

#pragma once
#include "inode.hpp"
#include "pool_node.hpp" // PoolNode, PoolObjectNode
// node.hpp — Node<> and ObjectNode<> as thin wrappers over PoolNode<>.
//
// Each Node owns a private single-thread ThreadPool so the API is unchanged:
// node.start() / node.stop() are self-contained with no external scheduler.
// Internally, all execution goes through PoolNode::fire_once() — the same code
// path as explicitly pool-scheduled nodes.
//
// To share a thread pool across multiple nodes, use make_pool_node() directly.
namespace kpn {
namespace detail {
// Private base initialized before PoolNode so its pool can be passed to the
// PoolNode constructor (C++ initialises bases left-to-right).
struct NodePrivatePool {
std::shared_ptr<ThreadPool> pool{std::make_shared<ThreadPool>(1)};
};
} // namespace detail
// ── Node ─────────────────────────────────────────────────────────────────────
template<auto Func,
typename InputTag = in<>,
typename OutputTag = out<>,
fixed_string Label = "",
std::size_t UniqueTag = 0>
class Node;
template<auto Func, fixed_string... InNames, fixed_string... OutNames,
fixed_string Label, std::size_t UniqueTag>
class Node<Func, in<InNames...>, out<OutNames...>, Label, UniqueTag>
: private detail::NodePrivatePool
, public PoolNode<Func, in<InNames...>, out<OutNames...>, Label, UniqueTag> {
using Base = PoolNode<Func, in<InNames...>, out<OutNames...>, Label, UniqueTag>;
public:
explicit Node(std::size_t fifo_capacity = 5)
: detail::NodePrivatePool{}
, Base(pool, fifo_capacity)
{}
~Node() override { stop(); }
void start() override { pool->start(); Base::start(); }
void stop() override { Base::stop(); pool->stop(); }
};
// ── ObjectNode ────────────────────────────────────────────────────────────────
template<typename Obj,
typename InputTag = in<>,
typename OutputTag = out<>,
fixed_string Label = "",
std::size_t UniqueTag = 0>
class ObjectNode;
template<typename Obj, fixed_string... InNames, fixed_string... OutNames,
fixed_string Label, std::size_t UniqueTag>
class ObjectNode<Obj, in<InNames...>, out<OutNames...>, Label, UniqueTag>
: private detail::NodePrivatePool
, public PoolObjectNode<Obj, in<InNames...>, out<OutNames...>, Label, UniqueTag> {
using Base = PoolObjectNode<Obj, in<InNames...>, out<OutNames...>, Label, UniqueTag>;
public:
explicit ObjectNode(Obj& obj, std::size_t fifo_capacity = 5)
: detail::NodePrivatePool{}
, Base(obj, pool, fifo_capacity)
{}
~ObjectNode() override { stop(); }
void start() override { pool->start(); Base::start(); }
void stop() override { Base::stop(); pool->stop(); }
};
// ── make_node overloads for callable objects ──────────────────────────────────
template<typename Obj>
auto make_node(Obj& obj, std::size_t fifo_capacity = 5) {
return ObjectNode<Obj, in<>, out<>>(obj, fifo_capacity);
}
template<typename Obj, fixed_string... InNames>
auto make_node(Obj& obj, in<InNames...>, std::size_t fifo_capacity = 5) {
return ObjectNode<Obj, in<InNames...>, out<>>(obj, fifo_capacity);
}
template<typename Obj, fixed_string... OutNames>
auto make_node(Obj& obj, out<OutNames...>, std::size_t fifo_capacity = 5) {
return ObjectNode<Obj, in<>, out<OutNames...>>(obj, fifo_capacity);
}
template<typename Obj, fixed_string... InNames, fixed_string... OutNames>
auto make_node(Obj& obj, in<InNames...>, out<OutNames...>, std::size_t fifo_capacity = 5) {
return ObjectNode<Obj, in<InNames...>, out<OutNames...>>(obj, fifo_capacity);
}
// ── make_node factory (NTTP) ──────────────────────────────────────────────────
template<auto Func, fixed_string Label = "", std::size_t UniqueTag = 0>
auto make_node(std::size_t fifo_capacity = 5) {
return Node<Func, in<>, out<>, Label, UniqueTag>(fifo_capacity);
}
template<auto Func, fixed_string Label = "", std::size_t UniqueTag = 0,
fixed_string... InNames>
auto make_node(in<InNames...>, std::size_t fifo_capacity = 5) {
return Node<Func, in<InNames...>, out<>, Label, UniqueTag>(fifo_capacity);
}
template<auto Func, fixed_string Label = "", std::size_t UniqueTag = 0,
fixed_string... OutNames>
auto make_node(out<OutNames...>, std::size_t fifo_capacity = 5) {
return Node<Func, in<>, out<OutNames...>, Label, UniqueTag>(fifo_capacity);
}
template<auto Func, fixed_string Label = "", std::size_t UniqueTag = 0,
fixed_string... InNames, fixed_string... OutNames>
auto make_node(in<InNames...>, out<OutNames...>, std::size_t fifo_capacity = 5) {
return Node<Func, in<InNames...>, out<OutNames...>, Label, UniqueTag>(fifo_capacity);
}
} // namespace kpn