void Logger::addOutput(ILogOutput *out, LogLevel lev)
{
+ MutexAutoLock lock(m_mutex);
m_outputs[lev].push_back(out);
m_has_outputs[lev] = true;
}
void Logger::addOutputMasked(ILogOutput *out, LogLevelMask mask)
{
+ MutexAutoLock lock(m_mutex);
for (size_t i = 0; i < LL_MAX; i++) {
if (mask & LOGLEVEL_TO_MASKLEVEL(i)) {
m_outputs[i].push_back(out);
void Logger::addOutputMaxLevel(ILogOutput *out, LogLevel lev)
{
+ MutexAutoLock lock(m_mutex);
assert(lev < LL_MAX);
for (size_t i = 0; i <= lev; i++) {
m_outputs[i].push_back(out);
LogLevelMask Logger::removeOutput(ILogOutput *out)
{
+ MutexAutoLock lock(m_mutex);
LogLevelMask ret_mask = 0;
for (size_t i = 0; i < LL_MAX; i++) {
std::vector<ILogOutput *>::iterator it;
default: break;
}
}
-
- m_buffer.push(color.append(line));
+ MutexAutoLock lock(m_buffer_mutex);
+ m_buffer.emplace(color.append(line));
}
#if !defined(_WIN32) // POSIX
#include <unistd.h>
#endif
+#include "threading/mutex_auto_lock.h"
#include "util/basic_macros.h"
#include "util/stream.h"
#include "irrlichttypes.h"
void clear()
{
+ MutexAutoLock lock(m_buffer_mutex);
m_buffer = std::queue<std::string>();
}
bool empty() const
{
+ MutexAutoLock lock(m_buffer_mutex);
return m_buffer.empty();
}
std::string get()
{
- if (empty())
+ MutexAutoLock lock(m_buffer_mutex);
+ if (m_buffer.empty())
return "";
- std::string s = m_buffer.front();
+ std::string s = std::move(m_buffer.front());
m_buffer.pop();
return s;
}
private:
+ // g_logger serializes calls to logRaw() with a mutex, but that
+ // doesn't prevent get() / clear() from being called on top of it.
+ // This mutex prevents that.
+ mutable std::mutex m_buffer_mutex;
std::queue<std::string> m_buffer;
Logger &m_logger;
};