#pragma once #include #include #include #include #include #include #include class AsyncLogger { public: // Singleton - jedna instancja loggera na całą grę static AsyncLogger& getInstance() { static AsyncLogger instance; return instance; } // Dodaj wiadomość do kolejki (wywoływane z gry) - to jest super szybkie void log(const std::string& message) { std::lock_guard lock(queueMutex); logQueue.push(message); cv.notify_one(); // Obudź wątek loggera } // Uruchom wątek (wywołaj raz na początku programu) void start() { running = true; loggingThread = std::thread(&AsyncLogger::processQueue, this); } // Zatrzymaj wątek (wywołaj przy zamykaniu) void stop() { running = false; cv.notify_one(); if (loggingThread.joinable()) { loggingThread.join(); } } private: AsyncLogger() : running(false) {} ~AsyncLogger() { stop(); } // To jest funkcja, która działa w osobnym wątku void processQueue() { while (running || !logQueue.empty()) { std::unique_lock lock(queueMutex); // Czekaj, aż coś pojawi się w kolejce lub zakończymy program cv.wait(lock, [this] { return !logQueue.empty() || !running; }); while (!logQueue.empty()) { std::string msg = logQueue.front(); logQueue.pop(); // Zwalniamy mutex przed wypisywaniem, żeby nie blokować głównego wątku // gdy konsola jest "zamrożona" przez użytkownika lock.unlock(); std::cout << msg << std::endl; lock.lock(); } } } std::thread loggingThread; std::mutex queueMutex; std::condition_variable cv; std::queue logQueue; std::atomic running; }; // Makro dla wygody używania #define LOG(msg) AsyncLogger::getInstance().log(msg)