#pragma once #include #include #include #include #include "text/text.hpp" #include "utils/globals.hpp" namespace Nimbin { class CppHighlightSystem { public: ~CppHighlightSystem() { if (_worker.joinable()) _worker.join(); } void request(const std::string& source, uint64_t gen) { if (source == _last_requested) return; _last_requested = source; if (_running.load()) { _redo = true; return; } spawn(source, gen); } bool poll(DynArray& out, uint64_t& out_gen) { if (!_done.load()) return false; { std::lock_guard lk(_mtx); out = _pending; out_gen = _result_gen; } _done.store(false); if (_worker.joinable()) _worker.join(); _running.store(false); if (_redo) { _redo = false; spawn(_last_requested, _last_gen_pending); } return true; } private: DynArray _pending; std::string _last_requested; std::thread _worker; std::mutex _mtx; uint64_t _result_gen { 0 }; uint64_t _last_gen_pending { 0 }; std::atomic _running { false }; std::atomic _done { false }; bool _redo { false }; void spawn(const std::string& source, uint64_t gen) { if (_worker.joinable()) _worker.join(); _running.store(true); _done.store(false); _last_gen_pending = gen; _worker = std::thread([this, source, gen]() { DynArray spans = Text::CppHighlight::classify(source); { std::lock_guard lk(_mtx); _pending = std::move(spans); _result_gen = gen; } _done.store(true); }); } }; } // namespace Nimbin