75 lines
2.1 KiB
C++
75 lines
2.1 KiB
C++
#pragma once
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <thread>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <queue>
|
|
#include <atomic>
|
|
|
|
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<std::mutex> 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<std::mutex> 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<std::string> logQueue;
|
|
std::atomic<bool> running;
|
|
};
|
|
|
|
// Makro dla wygody używania
|
|
#define LOG(msg) AsyncLogger::getInstance().log(msg) |