mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-06-28 01:49:33 -06:00
LogManager: Stop using manual memory management
This fixes a memory leak that would occur when the Android frontend calls LogManager::Init more than once in order to reload settings. Note that the log window listener is now owned by LogManager instead of by the frontend, making it consistent with the other log listeners.
This commit is contained in:
@ -8,6 +8,7 @@
|
|||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -151,8 +152,8 @@ LogManager::LogManager()
|
|||||||
m_log[LogType::WII_IPC] = {"WII_IPC", "WII IPC"};
|
m_log[LogType::WII_IPC] = {"WII_IPC", "WII IPC"};
|
||||||
|
|
||||||
RegisterListener(LogListener::FILE_LISTENER,
|
RegisterListener(LogListener::FILE_LISTENER,
|
||||||
new FileLogListener(File::GetUserPath(F_MAINLOG_IDX)));
|
std::make_unique<FileLogListener>(File::GetUserPath(F_MAINLOG_IDX)));
|
||||||
RegisterListener(LogListener::CONSOLE_LISTENER, new ConsoleListener());
|
RegisterListener(LogListener::CONSOLE_LISTENER, std::make_unique<ConsoleListener>());
|
||||||
|
|
||||||
// Set up log listeners
|
// Set up log listeners
|
||||||
LogLevel verbosity = Config::Get(LOGGER_VERBOSITY);
|
LogLevel verbosity = Config::Get(LOGGER_VERBOSITY);
|
||||||
@ -171,12 +172,7 @@ LogManager::LogManager()
|
|||||||
m_path_cutoff_point = DeterminePathCutOffPoint();
|
m_path_cutoff_point = DeterminePathCutOffPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
LogManager::~LogManager()
|
LogManager::~LogManager() = default;
|
||||||
{
|
|
||||||
// The log window listener pointer is owned by the GUI code.
|
|
||||||
delete m_listeners[LogListener::CONSOLE_LISTENER];
|
|
||||||
delete m_listeners[LogListener::FILE_LISTENER];
|
|
||||||
}
|
|
||||||
|
|
||||||
void LogManager::SaveSettings()
|
void LogManager::SaveSettings()
|
||||||
{
|
{
|
||||||
@ -273,9 +269,9 @@ const char* LogManager::GetFullName(LogType type) const
|
|||||||
return m_log[type].m_full_name;
|
return m_log[type].m_full_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::RegisterListener(LogListener::LISTENER id, LogListener* listener)
|
void LogManager::RegisterListener(LogListener::LISTENER id, std::unique_ptr<LogListener> listener)
|
||||||
{
|
{
|
||||||
m_listeners[id] = listener;
|
m_listeners[id] = std::move(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::EnableListener(LogListener::LISTENER id, bool enable)
|
void LogManager::EnableListener(LogListener::LISTENER id, bool enable)
|
||||||
@ -289,23 +285,22 @@ bool LogManager::IsListenerEnabled(LogListener::LISTENER id) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Singleton. Ugh.
|
// Singleton. Ugh.
|
||||||
static LogManager* s_log_manager;
|
static std::unique_ptr<LogManager> s_log_manager;
|
||||||
|
|
||||||
LogManager* LogManager::GetInstance()
|
LogManager* LogManager::GetInstance()
|
||||||
{
|
{
|
||||||
return s_log_manager;
|
return s_log_manager.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::Init()
|
void LogManager::Init()
|
||||||
{
|
{
|
||||||
s_log_manager = new LogManager();
|
s_log_manager = std::unique_ptr<LogManager>(new LogManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogManager::Shutdown()
|
void LogManager::Shutdown()
|
||||||
{
|
{
|
||||||
if (s_log_manager)
|
if (s_log_manager)
|
||||||
s_log_manager->SaveSettings();
|
s_log_manager->SaveSettings();
|
||||||
delete s_log_manager;
|
s_log_manager.reset();
|
||||||
s_log_manager = nullptr;
|
|
||||||
}
|
}
|
||||||
} // namespace Common::Log
|
} // namespace Common::Log
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
class LogManager
|
class LogManager final
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct LogContainer
|
struct LogContainer
|
||||||
@ -41,6 +42,8 @@ public:
|
|||||||
bool m_enable = false;
|
bool m_enable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
~LogManager();
|
||||||
|
|
||||||
static LogManager* GetInstance();
|
static LogManager* GetInstance();
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
@ -60,7 +63,7 @@ public:
|
|||||||
const char* GetShortName(LogType type) const;
|
const char* GetShortName(LogType type) const;
|
||||||
const char* GetFullName(LogType type) const;
|
const char* GetFullName(LogType type) const;
|
||||||
|
|
||||||
void RegisterListener(LogListener::LISTENER id, LogListener* listener);
|
void RegisterListener(LogListener::LISTENER id, std::unique_ptr<LogListener> listener);
|
||||||
void EnableListener(LogListener::LISTENER id, bool enable);
|
void EnableListener(LogListener::LISTENER id, bool enable);
|
||||||
bool IsListenerEnabled(LogListener::LISTENER id) const;
|
bool IsListenerEnabled(LogListener::LISTENER id) const;
|
||||||
|
|
||||||
@ -68,7 +71,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
LogManager();
|
LogManager();
|
||||||
~LogManager();
|
|
||||||
|
|
||||||
LogManager(const LogManager&) = delete;
|
LogManager(const LogManager&) = delete;
|
||||||
LogManager& operator=(const LogManager&) = delete;
|
LogManager& operator=(const LogManager&) = delete;
|
||||||
@ -79,7 +81,7 @@ private:
|
|||||||
|
|
||||||
LogLevel m_level;
|
LogLevel m_level;
|
||||||
EnumMap<LogContainer, LAST_LOG_TYPE> m_log{};
|
EnumMap<LogContainer, LAST_LOG_TYPE> m_log{};
|
||||||
std::array<LogListener*, LogListener::NUMBER_OF_LISTENERS> m_listeners{};
|
std::array<std::unique_ptr<LogListener>, LogListener::NUMBER_OF_LISTENERS> m_listeners{};
|
||||||
BitSet32 m_listener_ids;
|
BitSet32 m_listener_ids;
|
||||||
size_t m_path_cutoff_point = 0;
|
size_t m_path_cutoff_point = 0;
|
||||||
};
|
};
|
||||||
|
@ -52,15 +52,16 @@ LogWidget::LogWidget(QWidget* parent) : QDockWidget(parent), m_timer(new QTimer(
|
|||||||
|
|
||||||
connect(&Settings::Instance(), &Settings::DebugFontChanged, this, &LogWidget::UpdateFont);
|
connect(&Settings::Instance(), &Settings::DebugFontChanged, this, &LogWidget::UpdateFont);
|
||||||
|
|
||||||
Common::Log::LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER, this);
|
Common::Log::LogManager::GetInstance()->RegisterListener(
|
||||||
|
Common::Log::LogListener::LOG_WINDOW_LISTENER, std::make_unique<LogListenerImpl>(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
LogWidget::~LogWidget()
|
LogWidget::~LogWidget()
|
||||||
{
|
{
|
||||||
SaveSettings();
|
SaveSettings();
|
||||||
|
|
||||||
Common::Log::LogManager::GetInstance()->RegisterListener(LogListener::LOG_WINDOW_LISTENER,
|
Common::Log::LogManager::GetInstance()->RegisterListener(
|
||||||
nullptr);
|
Common::Log::LogListener::LOG_WINDOW_LISTENER, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogWidget::UpdateLog()
|
void LogWidget::UpdateLog()
|
||||||
|
@ -18,7 +18,7 @@ class QPlainTextEdit;
|
|||||||
class QPushButton;
|
class QPushButton;
|
||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
class LogWidget final : public QDockWidget, Common::Log::LogListener
|
class LogWidget final : public QDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@ -29,6 +29,23 @@ protected:
|
|||||||
void closeEvent(QCloseEvent*) override;
|
void closeEvent(QCloseEvent*) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// LogListener instances are owned by LogManager, so we can't make LogWidget inherit from
|
||||||
|
// LogListener, since Qt should be in control of LogWidget's lifetime. Instead we have
|
||||||
|
// this LogListenerImpl class to act as an adapter.
|
||||||
|
class LogListenerImpl final : public Common::Log::LogListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit LogListenerImpl(LogWidget* log_widget) : m_log_widget(log_widget) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Log(Common::Log::LogLevel level, const char* text) override
|
||||||
|
{
|
||||||
|
m_log_widget->Log(level, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
LogWidget* m_log_widget;
|
||||||
|
};
|
||||||
|
|
||||||
void UpdateLog();
|
void UpdateLog();
|
||||||
void UpdateFont();
|
void UpdateFont();
|
||||||
void CreateWidgets();
|
void CreateWidgets();
|
||||||
@ -36,7 +53,7 @@ private:
|
|||||||
void LoadSettings();
|
void LoadSettings();
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
|
|
||||||
void Log(Common::Log::LogLevel level, const char* text) override;
|
void Log(Common::Log::LogLevel level, const char* text);
|
||||||
|
|
||||||
// Log
|
// Log
|
||||||
QCheckBox* m_log_wrap;
|
QCheckBox* m_log_wrap;
|
||||||
|
Reference in New Issue
Block a user