Intro
Я работаю над многопоточным кроссплатформенным средством регистрации, которое предназначено для входа в консоль и / или файл.Однако проблема, с которой я сталкиваюсь сейчас, связана только с ведением журнала консоли.
Разбивка проблемы
Способ работы регистратора заключается в добавлении строки в очередь строк.,В потоке LogToConsole существует метод wait, который ожидает, пока в очередь не будет добавлена строка.Когда это происходит, он должен получить уведомление и распечатать, затем выдвинуть и разблокировать.
Используемые переменные
class Logger
{
public:
friend void LogToConsole(Logger* logger);
private:
std::atomic_flag _ThreadIsRunning { ATOMIC_FLAG_INIT };
std::thread _LogThread;
std::queue<std::string> _LogBuffer;
std::map<std::thread::id, std::string> _ThreadName;
std::mutex _LogMutex;
std::mutex _AppendLock;
std::condition_variable _LogLock;
...
Место, куда я добавляю данные в буфер
template<LogSeverity severity>
void Logger::Log(std::stringstream& message)
{
std::stringstream log;
log << _ThreadName[std::this_thread::get_id()] << ":\t";
log << message.str();
std::unique_lock<std::mutex> logAppendLock(_AppendLock);
_LogBuffer.push(log.str());
logAppendLock.unlock();
_LogLock.notify_one();
}
template<LogSeverity severity>
void Logger::Log(std::string message)
{
std::stringstream log;
log << message.c_str();
this->Log<severity>(log);
}
Поток , который выполняется в отдельном цикле (однако обратите внимание, что этот метод не является частью класса регистратора):
void LogToConsole(Logger* logger)
{
do
{
std::unique_lock<std::mutex> lock(logger->_LogMutex);
logger->_LogLock.wait(lock);
std::printf("%s", logger->_LogBuffer.back().c_str());
logger->_LogBuffer.pop();
lock.unlock();
} while (logger->_ThreadIsRunning.test_and_set() || !logger->_LogBuffer.empty());
}
Место создания потока
Logger::Logger() : _LogThread(), _LogBuffer(), _ThreadName(), _LogMutex()
{
_ThreadIsRunning.test_and_set();
_LogThread = std::thread(LogToConsole, this);
}
Тестовый корпус
std::shared_ptr<Logger> engineLogger = std::make_shared<Logger>();
engineLogger->SetThreadName("EngineLogger");
std::shared_ptr<Logger> coreLogger = std::make_shared<Logger>();
coreLogger->SetThreadName("CoreLogger");
while(true)
{
engineLogger->Log<LOG_INFO>("LOG\n");
coreLogger->Log<LOG_WARNING>("WARNING\n");
}
Код, похоже, работает как потокобезопасный, без данных и т. Д., Но он вылетаетчерез 5-10 ~ секунд.Я искал, если есть люди, у которых есть подобная проблема, это, кажется, не имеет место.
Я, однако, не очень опытный с параллельным программированием, таким образом, делаюне сейчас, как очень легко справиться с подобными проблемами.
Надеюсь, что кто-то может решить проблему или дать мне несколько советов, чтобы предотвратить проблему.