Skip to content

Commit

Permalink
RMG: rate limit callbacks to prevent freezing
Browse files Browse the repository at this point in the history
  • Loading branch information
Rosalie241 committed May 24, 2024
1 parent c815756 commit 85c1c1a
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 38 deletions.
37 changes: 35 additions & 2 deletions Source/RMG/Callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
*/
#include "Callbacks.hpp"

#include <QTimerEvent>
#include <QMutex>

#include <RMG-Core/Core.hpp>

//
Expand All @@ -18,6 +21,9 @@
static CoreCallbacks* l_CoreCallbacks = nullptr;
static bool l_showVerboseMessages = false;

static QMutex l_CallbackMessagesMutex;
static QList<CoreCallbackMessage> l_CallbackMessages;

//
// Exported Functions
//
Expand All @@ -37,23 +43,48 @@ bool CoreCallbacks::Init(void)
// needed for Qt
qRegisterMetaType<CoreDebugMessageType>("CoreDebugMessageType");
qRegisterMetaType<CoreDebugMessageType>("CoreStateCallbackType");
qRegisterMetaType<CoreCallbackMessage>("CoreCallbackMessage");

this->LoadSettings();

l_CoreCallbacks = this;
return CoreSetupCallbacks(this->coreDebugCallback, this->coreStateCallback);

if (!CoreSetupCallbacks(this->coreDebugCallback, this->coreStateCallback))
{
return false;
}

this->callbackTimerId = this->startTimer(100);
return true;
}

void CoreCallbacks::Stop(void)
{
l_CoreCallbacks = nullptr;

this->killTimer(this->callbackTimerId);
this->callbackTimerId = -1;
}

void CoreCallbacks::LoadSettings(void)
{
l_showVerboseMessages = CoreSettingsGetBoolValue(SettingsID::GUI_ShowVerboseLogMessages);
}

void CoreCallbacks::timerEvent(QTimerEvent *event)
{
if (event->timerId() == this->callbackTimerId)
{
l_CallbackMessagesMutex.lock();
if (!l_CallbackMessages.isEmpty())
{
emit this->OnCoreDebugCallback(l_CallbackMessages);
l_CallbackMessages.clear();
}
l_CallbackMessagesMutex.unlock();
}
}

void CoreCallbacks::coreDebugCallback(CoreDebugMessageType type, std::string context, std::string message)
{
if (l_CoreCallbacks == nullptr)
Expand All @@ -67,7 +98,9 @@ void CoreCallbacks::coreDebugCallback(CoreDebugMessageType type, std::string con
return;
}

emit l_CoreCallbacks->OnCoreDebugCallback(type, QString::fromStdString(context), QString::fromStdString(message));
l_CallbackMessagesMutex.lock();
l_CallbackMessages.append({type, QString::fromStdString(context), QString::fromStdString(message)});
l_CallbackMessagesMutex.unlock();
}

void CoreCallbacks::coreStateCallback(CoreStateCallbackType type, int value)
Expand Down
16 changes: 15 additions & 1 deletion Source/RMG/Callbacks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,20 @@
#ifndef RMG_CALLBACKS_HPP
#define RMG_CALLBACKS_HPP

#include <QList>
#include <QObject>

#include <RMG-Core/Core.hpp>

#include <string>

struct CoreCallbackMessage
{
CoreDebugMessageType Type;
QString Context;
QString Message;
};

class CoreCallbacks : public QObject
{
Q_OBJECT
Expand All @@ -29,12 +37,18 @@ class CoreCallbacks : public QObject

void LoadSettings(void);

protected:
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;

private:
static void coreDebugCallback(CoreDebugMessageType type, std::string context, std::string message);
static void coreStateCallback(CoreStateCallbackType type, int value);


int callbackTimerId = -1;

signals:
void OnCoreDebugCallback(CoreDebugMessageType type, QString context, QString message);
void OnCoreDebugCallback(QList<CoreCallbackMessage> callbackMessages);
void OnCoreStateCallback(CoreStateCallbackType type, int value);
};

Expand Down
47 changes: 25 additions & 22 deletions Source/RMG/UserInterface/Dialog/LogDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,34 +34,37 @@ int LogDialog::GetLineCount(void)
return this->plainTextEdit->document()->lineCount();
}

void LogDialog::AddLogLine(CoreDebugMessageType type, QString context, QString line)
void LogDialog::AddMessages(const QList<CoreCallbackMessage>& messages)
{
QString text;

text = context;

switch (type)
for (const auto& message : messages)
{
case CoreDebugMessageType::Error:
text += "[ERROR] ";
break;
case CoreDebugMessageType::Info:
text += "[INFO] ";
break;
case CoreDebugMessageType::Verbose:
text += "[VERBOSE] ";
break;
case CoreDebugMessageType::Warning:
text += "[WARNING] ";
break;
case CoreDebugMessageType::Status:
text += "[STATUS] ";
break;
}
text = message.Context;

text += line;
switch (message.Type)
{
case CoreDebugMessageType::Error:
text += "[ERROR] ";
break;
case CoreDebugMessageType::Info:
text += "[INFO] ";
break;
case CoreDebugMessageType::Verbose:
text += "[VERBOSE] ";
break;
case CoreDebugMessageType::Warning:
text += "[WARNING] ";
break;
case CoreDebugMessageType::Status:
text += "[STATUS] ";
break;
}

this->plainTextEdit->appendPlainText(text);
text += message.Message;

this->plainTextEdit->appendPlainText(text);
}
}

void LogDialog::Clear(void)
Expand Down
5 changes: 4 additions & 1 deletion Source/RMG/UserInterface/Dialog/LogDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#ifndef LOGDIALOG_HPP
#define LOGDIALOG_HPP

#include "Callbacks.hpp"

#include <QList>
#include <QWidget>
#include <QDialog>

Expand All @@ -33,7 +36,7 @@ class LogDialog : public QDialog, private Ui::LogDialog

int GetLineCount(void);

void AddLogLine(CoreDebugMessageType type, QString context, QString line);
void AddMessages(const QList<CoreCallbackMessage>& messages);
void Clear(void);
};
} // namespace Dialog
Expand Down
24 changes: 13 additions & 11 deletions Source/RMG/UserInterface/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2355,43 +2355,45 @@ void MainWindow::on_VidExt_ToggleFS(bool fullscreen)
}
}

void MainWindow::on_Core_DebugCallback(CoreDebugMessageType type, QString context, QString message)
void MainWindow::on_Core_DebugCallback(QList<CoreCallbackMessage> messages)
{
// pass callback to the log window
this->logDialog.AddLogLine(type, context, message);
// pass callback messages to the log window
this->logDialog.AddMessages(messages);

// only display in statusbar when emulation is running
if (!this->emulationThread->isRunning())
{
return;
}

if (!context.startsWith("[CORE]"))
const CoreCallbackMessage& statusbarMessage = messages.last();

if (!statusbarMessage.Context.startsWith("[CORE]"))
{
return;
}

// drop verbose messages
if (type == CoreDebugMessageType::Verbose)
if (statusbarMessage.Type == CoreDebugMessageType::Verbose)
{
return;
}

// drop IS64 messages
if (message.startsWith("IS64:"))
if (statusbarMessage.Message.startsWith("IS64:"))
{
return;
}

if (type == CoreDebugMessageType::Error)
if (statusbarMessage.Type == CoreDebugMessageType::Error)
{
// when we've reached 50 of the same error in the same
// emulation run, we'll stop displaying it
if (this->ui_DebugCallbackErrors.count(message) < 50)
if (this->ui_DebugCallbackErrors.count(statusbarMessage.Message) < 50)
{
this->showErrorMessage("Core Error", message, false);
this->showErrorMessage("Core Error", statusbarMessage.Message, false);
}
this->ui_DebugCallbackErrors.append(message);
this->ui_DebugCallbackErrors.append(statusbarMessage.Message);
return;
}

Expand All @@ -2400,7 +2402,7 @@ void MainWindow::on_Core_DebugCallback(CoreDebugMessageType type, QString contex
return;
}

this->ui_StatusBar_Label->setText(message);
this->ui_StatusBar_Label->setText(statusbarMessage.Message);

// reset label deletion timer
if (this->ui_TimerId != 0)
Expand Down
2 changes: 1 addition & 1 deletion Source/RMG/UserInterface/MainWindow.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
void on_VidExt_ResizeWindow(int width, int height);
void on_VidExt_ToggleFS(bool fullscreen);

void on_Core_DebugCallback(CoreDebugMessageType type, QString context, QString message);
void on_Core_DebugCallback(QList<CoreCallbackMessage> messages);
void on_Core_StateCallback(CoreStateCallbackType type, int value);
};
} // namespace UserInterface
Expand Down

0 comments on commit 85c1c1a

Please sign in to comment.