Я работаю с многопоточным кодом для игрового проекта, и немного устал от сортировки stdout vomit, созданного двумя потоками, использующими cout для отладки сообщений одновременно.Я провел некоторое исследование и смотрел на стену в течение часа или двух, прежде чем придумал «что-то».Следующий код использует SFML для хранения времени и потоков.Мьютексы SFML - это просто обернутые критические секции в окнах.
Заголовок:
#include <SFML\System.hpp>
#include <iostream>
class OutputStreamHack
{
public:
OutputStreamHack();
~OutputStreamHack();
ostream& outputHijack(ostream &os);
private:
sf::Clock myRunTime;
sf::Mutex myMutex;
};
static OutputStream OUTHACK;
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue);
Реализация:
#include <SFML\System.hpp>
#include <iostream>
#include "OutputStreamHack.h"
using namespace std;
OutputStreamHack::OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
OutputStreamHack::~OutputStreamHack()
{
myMutex.Unlock();
myRunTime.Reset();
}
ostream& OutputStreamHack::outputHijack(ostream &os)
{
sf::Lock lock(myMutex);
os<<"<"<<myRunTime.GetElapsedTime()<<","<<GetCurrentThreadId()<<"> "<<flush;
return os;
}
ostream& operator<<(ostream& os, const OutputStreamHack& inputValue)
{
OUTHACK.outputHijack(os);
return os;
}
Использование:
cout<<OUTHACK<<val1<<val2<<val3....<<endl;
ОКТаким образом, этот способ работает через перегруженный оператор вставки, который обеспечивает безопасность потока, блокируя итератор в статическом объекте, а затем сбрасывая буфер.Если я правильно понимаю этот процесс (я в основном программист-самоучка), cout обрабатывает элементы своей цепочки вставки от конца к началу, передавая переменную ostream по цепочке для каждого элемента, который должен быть добавлен к потоку.Как только он достигает элемента OUTHACK, вызывается перегруженный оператор, мьютекс блокируется и поток сбрасывается.
Я добавил некоторую информацию об отладке идентификатора времени / потока в вывод для проверки.Пока что мое тестирование показывает, что этот метод работает.У меня есть несколько потоков, набирающих cout с несколькими аргументами, и все идет в правильном порядке.
Из того, что я прочитал во время исследования этой проблемы, отсутствие безопасности потоков в cout кажется довольно распространенной проблемой, котораялюди сталкиваются, углубляясь в многопоточное программирование.Я пытаюсь понять, является ли техника, которую я использую, простым решением проблемы, или я думаю, что я умен, но упускаю что-то важное.
По моему опыту, слово умный, когда используется дляОписание программирования - это просто кодовое слово для отсроченной боли.Я что-то здесь делаю или просто преследую паршивых хаков по кругу?
Спасибо!