LogManager: replace set of LogListener pointers with bitset.

Mostly so we can iterate over which LogListeners are enabled without
having to aquire a lock.
This commit is contained in:
Scott Mansell
2015-10-04 00:34:36 +13:00
parent 83fa504cd9
commit 6153424b8c
4 changed files with 54 additions and 72 deletions

View File

@ -83,8 +83,8 @@ LogManager::LogManager()
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24"); m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE", "WII IPC WIIMOTE"); m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE", "WII IPC WIIMOTE");
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX)); RegisterListener(LogListener::FILE_LISTENER, new FileLogListener(File::GetUserPath(F_MAINLOG_IDX)));
m_consoleLog = new ConsoleListener(); RegisterListener(LogListener::CONSOLE_LISTENER, new ConsoleListener());
IniFile ini; IniFile ini;
ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX)); ini.Load(File::GetUserPath(F_LOGGERCONFIG_IDX));
@ -101,25 +101,20 @@ LogManager::LogManager()
logs->Get(container->GetShortName(), &enable, false); logs->Get(container->GetShortName(), &enable, false);
container->SetEnable(enable); container->SetEnable(enable);
if (enable && write_file) if (enable && write_file)
container->AddListener(m_fileLog); container->AddListener(LogListener::FILE_LISTENER);
if (enable && write_console) if (enable && write_console)
container->AddListener(m_consoleLog); container->AddListener(LogListener::CONSOLE_LISTENER);
} }
} }
LogManager::~LogManager() LogManager::~LogManager()
{ {
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
}
for (LogContainer* container : m_Log) for (LogContainer* container : m_Log)
delete container; delete container;
delete m_fileLog; // The log window listener pointer is owned by the GUI code.
delete m_consoleLog; delete m_listeners[LogListener::CONSOLE_LISTENER];
delete m_listeners[LogListener::FILE_LISTENER];
} }
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
@ -141,7 +136,9 @@ void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
#ifdef ANDROID #ifdef ANDROID
__android_log_write(ANDROID_LOG_INFO, "Dolphinemu", msg.c_str()); __android_log_write(ANDROID_LOG_INFO, "Dolphinemu", msg.c_str());
#endif #endif
log->Trigger(level, msg.c_str());
for (auto listener_id : *log)
m_listeners[listener_id]->Log(level, msg.c_str());
} }
void LogManager::Init() void LogManager::Init()
@ -163,29 +160,6 @@ LogContainer::LogContainer(const std::string& shortName, const std::string& full
{ {
} }
// LogContainer
void LogContainer::AddListener(LogListener *listener)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.insert(listener);
}
void LogContainer::RemoveListener(LogListener *listener)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.erase(listener);
}
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
{
std::lock_guard<std::mutex> lk(m_listeners_lock);
for (LogListener* listener : m_listeners)
{
listener->Log(level, msg);
}
}
FileLogListener::FileLogListener(const std::string& filename) FileLogListener::FileLogListener(const std::string& filename)
{ {
OpenFStream(m_logfile, filename, std::ios::app); OpenFStream(m_logfile, filename, std::ios::app);

View File

@ -4,12 +4,14 @@
#pragma once #pragma once
#include <array>
#include <cstdarg> #include <cstdarg>
#include <fstream> #include <fstream>
#include <mutex> #include <mutex>
#include <set> #include <set>
#include <string> #include <string>
#include "Common/BitSet.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/NonCopyable.h" #include "Common/NonCopyable.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
@ -17,7 +19,6 @@
#define MAX_MESSAGES 8000 #define MAX_MESSAGES 8000
#define MAX_MSGLEN 1024 #define MAX_MSGLEN 1024
// pure virtual interface // pure virtual interface
class LogListener class LogListener
{ {
@ -25,6 +26,15 @@ public:
virtual ~LogListener() {} virtual ~LogListener() {}
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0; virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
enum LISTENER
{
FILE_LISTENER = 0,
CONSOLE_LISTENER,
LOG_WINDOW_LISTENER,
NUMBER_OF_LISTENERS // Must be last
};
}; };
class FileLogListener : public LogListener class FileLogListener : public LogListener
@ -54,8 +64,8 @@ public:
std::string GetShortName() const { return m_shortName; } std::string GetShortName() const { return m_shortName; }
std::string GetFullName() const { return m_fullName; } std::string GetFullName() const { return m_fullName; }
void AddListener(LogListener* listener); void AddListener(LogListener::LISTENER id) { m_listener_ids[id] = 1; }
void RemoveListener(LogListener* listener); void RemoveListener(LogListener::LISTENER id) { m_listener_ids[id] = 0; }
void Trigger(LogTypes::LOG_LEVELS, const char *msg); void Trigger(LogTypes::LOG_LEVELS, const char *msg);
@ -66,15 +76,18 @@ public:
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; } void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
bool HasListeners() const { return !m_listeners.empty(); } bool HasListeners() const { return m_listener_ids; }
typedef class BitSet32::Iterator iterator;
iterator begin() const { return m_listener_ids.begin(); }
iterator end() const { return m_listener_ids.end(); }
private: private:
std::string m_fullName; std::string m_fullName;
std::string m_shortName; std::string m_shortName;
bool m_enable; bool m_enable;
LogTypes::LOG_LEVELS m_level; LogTypes::LOG_LEVELS m_level;
std::mutex m_listeners_lock; BitSet32 m_listener_ids;
std::set<LogListener*> m_listeners;
}; };
class ConsoleListener; class ConsoleListener;
@ -83,9 +96,8 @@ class LogManager : NonCopyable
{ {
private: private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog;
static LogManager *m_logManager; // Singleton. Ugh. static LogManager *m_logManager; // Singleton. Ugh.
std::array<LogListener*, LogListener::NUMBER_OF_LISTENERS> m_listeners;
LogManager(); LogManager();
~LogManager(); ~LogManager();
@ -121,24 +133,19 @@ public:
return m_Log[type]->GetFullName(); return m_Log[type]->GetFullName();
} }
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener) void RegisterListener(LogListener::LISTENER id, LogListener *listener)
{ {
m_Log[type]->AddListener(listener); m_listeners[id] = listener;
} }
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener) void AddListener(LogTypes::LOG_TYPE type, LogListener::LISTENER id)
{ {
m_Log[type]->RemoveListener(listener); m_Log[type]->AddListener(id);
} }
FileLogListener *GetFileListener() const void RemoveListener(LogTypes::LOG_TYPE type, LogListener::LISTENER id)
{ {
return m_fileLog; m_Log[type]->RemoveListener(id);
}
ConsoleListener *GetConsoleListener() const
{
return m_consoleLog;
} }
static LogManager* GetInstance() static LogManager* GetInstance()

View File

@ -170,9 +170,9 @@ void LogConfigWindow::OnWriteFileChecked(wxCommandEvent& event)
if (m_checks->IsChecked(i)) if (m_checks->IsChecked(i))
{ {
if (m_writeFile) if (m_writeFile)
m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetFileListener()); m_LogManager->AddListener((LogTypes::LOG_TYPE)i, LogListener::FILE_LISTENER);
else else
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetFileListener()); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::FILE_LISTENER);
} }
} }
} }
@ -185,9 +185,9 @@ void LogConfigWindow::OnWriteConsoleChecked(wxCommandEvent& event)
if (m_checks->IsChecked(i)) if (m_checks->IsChecked(i))
{ {
if (m_writeConsole) if (m_writeConsole)
m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); m_LogManager->AddListener((LogTypes::LOG_TYPE)i, LogListener::CONSOLE_LISTENER);
else else
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetConsoleListener()); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::CONSOLE_LISTENER);
} }
} }
} }
@ -200,9 +200,9 @@ void LogConfigWindow::OnWriteWindowChecked(wxCommandEvent& event)
if (m_checks->IsChecked(i)) if (m_checks->IsChecked(i))
{ {
if (m_writeWindow) if (m_writeWindow)
m_LogManager->AddListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogWindow); m_LogManager->AddListener((LogTypes::LOG_TYPE)i, LogListener::LOG_WINDOW_LISTENER);
else else
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, (LogListener *)m_LogWindow); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::LOG_WINDOW_LISTENER);
} }
} }
} }
@ -226,17 +226,17 @@ void LogConfigWindow::ToggleLog(int _logType, bool enable)
if (enable) if (enable)
{ {
if (m_writeWindow) if (m_writeWindow)
m_LogManager->AddListener(logType, (LogListener *)m_LogWindow); m_LogManager->AddListener(logType, LogListener::LOG_WINDOW_LISTENER);
if (m_writeFile) if (m_writeFile)
m_LogManager->AddListener(logType, m_LogManager->GetFileListener()); m_LogManager->AddListener(logType, LogListener::FILE_LISTENER);
if (m_writeConsole) if (m_writeConsole)
m_LogManager->AddListener(logType, m_LogManager->GetConsoleListener()); m_LogManager->AddListener(logType, LogListener::CONSOLE_LISTENER);
} }
else else
{ {
m_LogManager->RemoveListener(logType, (LogListener *)m_LogWindow); m_LogManager->RemoveListener(logType, LogListener::LOG_WINDOW_LISTENER);
m_LogManager->RemoveListener(logType, m_LogManager->GetFileListener()); m_LogManager->RemoveListener(logType, LogListener::FILE_LISTENER);
m_LogManager->RemoveListener(logType, m_LogManager->GetConsoleListener()); m_LogManager->RemoveListener(logType, LogListener::CONSOLE_LISTENER);
} }
} }

View File

@ -43,6 +43,7 @@ CLogWindow::CLogWindow(CFrame *parent, wxWindowID id, const wxPoint& pos,
Bind(wxEVT_TIMER, &CLogWindow::OnLogTimer, this); Bind(wxEVT_TIMER, &CLogWindow::OnLogTimer, this);
m_LogManager = LogManager::GetInstance(); m_LogManager = LogManager::GetInstance();
m_LogManager->RegisterListener(LogListener::LOG_WINDOW_LISTENER, this);
CreateGUIControls(); CreateGUIControls();
@ -82,14 +83,14 @@ void CLogWindow::CreateGUIControls()
logs->Get(m_LogManager->GetShortName((LogTypes::LOG_TYPE)i), &enable, false); logs->Get(m_LogManager->GetShortName((LogTypes::LOG_TYPE)i), &enable, false);
if (m_writeWindow && enable) if (m_writeWindow && enable)
m_LogManager->AddListener((LogTypes::LOG_TYPE)i, this); m_LogManager->AddListener((LogTypes::LOG_TYPE)i, LogListener::LOG_WINDOW_LISTENER);
else else
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, this); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::LOG_WINDOW_LISTENER);
if (m_writeFile && enable) if (m_writeFile && enable)
m_LogManager->AddListener((LogTypes::LOG_TYPE)i, m_LogManager->GetFileListener()); m_LogManager->AddListener((LogTypes::LOG_TYPE)i, LogListener::FILE_LISTENER);
else else
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, m_LogManager->GetFileListener()); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::FILE_LISTENER);
m_LogManager->SetLogLevel((LogTypes::LOG_TYPE)i, (LogTypes::LOG_LEVELS)(verbosity)); m_LogManager->SetLogLevel((LogTypes::LOG_TYPE)i, (LogTypes::LOG_LEVELS)(verbosity));
} }
@ -151,7 +152,7 @@ CLogWindow::~CLogWindow()
{ {
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{ {
m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, this); m_LogManager->RemoveListener((LogTypes::LOG_TYPE)i, LogListener::LOG_WINDOW_LISTENER);
} }
} }