#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 pool{std::make_shared(1)}; }; } // namespace detail // ── Node ───────────────────────────────────────────────────────────────────── template, typename OutputTag = out<>, fixed_string Label = "", std::size_t UniqueTag = 0> class Node; template class Node, out, Label, UniqueTag> : private detail::NodePrivatePool , public PoolNode, out, Label, UniqueTag> { using Base = PoolNode, out, 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 OutputTag = out<>, fixed_string Label = "", std::size_t UniqueTag = 0> class ObjectNode; template class ObjectNode, out, Label, UniqueTag> : private detail::NodePrivatePool , public PoolObjectNode, out, Label, UniqueTag> { using Base = PoolObjectNode, out, 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 auto make_node(Obj& obj, std::size_t fifo_capacity = 5) { return ObjectNode, out<>>(obj, fifo_capacity); } template auto make_node(Obj& obj, in, std::size_t fifo_capacity = 5) { return ObjectNode, out<>>(obj, fifo_capacity); } template auto make_node(Obj& obj, out, std::size_t fifo_capacity = 5) { return ObjectNode, out>(obj, fifo_capacity); } template auto make_node(Obj& obj, in, out, std::size_t fifo_capacity = 5) { return ObjectNode, out>(obj, fifo_capacity); } // ── make_node factory (NTTP) ────────────────────────────────────────────────── template auto make_node(std::size_t fifo_capacity = 5) { return Node, out<>, Label, UniqueTag>(fifo_capacity); } template auto make_node(in, std::size_t fifo_capacity = 5) { return Node, out<>, Label, UniqueTag>(fifo_capacity); } template auto make_node(out, std::size_t fifo_capacity = 5) { return Node, out, Label, UniqueTag>(fifo_capacity); } template auto make_node(in, out, std::size_t fifo_capacity = 5) { return Node, out, Label, UniqueTag>(fifo_capacity); } } // namespace kpn