std::cout << "Hello World" << std::endl;
Start Start foo1
foo2
work work
#include <iostream>
#include <sstream>
#include <thread>
#include <mutex>
#include <queue>
using namespace std;
class Logger {
class Message {
private:
ostringstream oss;
public:
Message() = default;
Message(Message&&) = default;
Message(const Message&) = delete;
public:
template<class Type>
Message& operator<<(const Type& text) {
oss << text;
return *this;
}
Message& operator<<(ostream& (*manip)(ostream&)) {
if (static_cast<ostream& (*)(ostream&)>(endl) == manip) {
Logger& logg = Logger::get_instance();
{
lock_guard<mutex> lock(logg.mtx);
logg.messages.push(oss.str());
}
oss.str("");
oss.flush();
oss.clear();
}
else {
oss << manip;
}
return *this;
}
};
private:
queue<string> messages;
bool is_work;
thread printer;
mutex mtx;
private:
Logger()
: is_work(true)
, printer(&Logger::print, this) {
}
~Logger() {
is_work = false;
printer.join();
}
public:
Logger(Logger&&) = delete;
Logger(const Logger&&) = delete;
public:
static Logger& get_instance() {
static Logger instace;
return instace;
}
private:
void print() {
while(is_work == true) {
while (messages.empty() == false) {
cout << messages.front() << endl;
messages.pop();
}
}
}
public:
template<class Type>
Message operator<<(const Type& text) {
return move(Message() << text);
}
Message operator<<(ostream& (*manip)(ostream&)) {
return move(Message() << manip);
}
};
Logger& logg = Logger::get_instance();
// Симуляция многопоточной работы
static int j = 0;
int main() {
for (size_t i = 0; i < 10; ++i) {
thread th1([]() {
logg << j++ << " Hello" << endl;
});
th1.detach();
thread th2([]() {
logg << j++ << " World" << endl;
});
th2.detach();
}
for(;;);
return 0;
}
<<
для логгирования не очень подходит, т.к. вынуждает использовать конструкции типа: oss << "Error: " << strerror(err) << "(" << err << ")";