// // Created by Grant Horner on 12/1/25. // #pragma once #include #include #include template struct Spawner { std::mutex mutex; std::condition_variable cv; std::atomic running; std::atomic paused; std::jthread timer; long long rate_secs; T values[N]; explicit Spawner(long long rate_secs); virtual void spawn(); template void for_each(F&& func) { std::lock_guard lock{mutex}; for (auto& value : values) { func(value); } } void start(); virtual ~Spawner(); }; template Spawner::Spawner(const long long rate_secs) : rate_secs(rate_secs) { } template void Spawner::spawn() { } template void Spawner::start() { running.store(true); timer = std::jthread([&] { while (running.load()) { const auto start = std::chrono::steady_clock::now(); std::unique_lock lock{mutex}; if (!paused.load()) { spawn(); } auto next = start + std::chrono::seconds(rate_secs); cv.wait_until(lock, next, [&] { return !running.load(); }); } }); } template Spawner::~Spawner() { running.store(false); cv.notify_all(); }