From 735ec2e86819311f50f90f3797b318e084442d29 Mon Sep 17 00:00:00 2001 From: Alex Spataru Date: Sun, 2 Jan 2022 00:46:20 -0500 Subject: [PATCH] Clean up JSON::Generator --- Serial-Studio.pro | 20 +++ assets/qml/Panes/Setup.qml | 1 - assets/qml/Panes/SetupPanes/Settings.qml | 17 --- src/JSON/Generator.cpp | 179 ++--------------------- src/JSON/Generator.h | 38 ----- 5 files changed, 33 insertions(+), 222 deletions(-) diff --git a/Serial-Studio.pro b/Serial-Studio.pro index a7cebba0..56b6da91 100644 --- a/Serial-Studio.pro +++ b/Serial-Studio.pro @@ -65,8 +65,28 @@ DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00 CONFIG += c++11 CONFIG += silent +*g++*: { + QMAKE_CXXFLAGS_RELEASE -= -O1 + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE *= -O3 + QMAKE_CXXFLAGS_RELEASE *= -Ofast + QMAKE_CXXFLAGS_RELEASE *= -flto +} + +*clang*: { + QMAKE_CXXFLAGS_RELEASE -= -O1 + QMAKE_CXXFLAGS_RELEASE -= -O2 + QMAKE_CXXFLAGS_RELEASE *= -O3 + QMAKE_CXXFLAGS_RELEASE *= -Ofast + QMAKE_CXXFLAGS_RELEASE *= -flto +} + *msvc*: { QMAKE_CXXFLAGS *= -MP + QMAKE_CXXFLAGS_RELEASE -= /O + QMAKE_CXXFLAGS_RELEASE *= /O2 + QMAKE_CXXFLAGS_RELEASE *= /GL + INCLUDEPATH += $$OUT_PWD INCLUDEPATH += $$OUT_PWD/debug INCLUDEPATH += $$OUT_PWD/release diff --git a/assets/qml/Panes/Setup.qml b/assets/qml/Panes/Setup.qml index 3b8980a7..38f6b8b0 100644 --- a/assets/qml/Panes/Setup.qml +++ b/assets/qml/Panes/Setup.qml @@ -110,7 +110,6 @@ Item { property alias endSequence: settings.endSequence property alias startSequence: settings.startSequence property alias separatorSequence: settings.separatorSequence - property alias multithreadedFrameProcessing: settings.multithreadedFrameProcessing } // diff --git a/assets/qml/Panes/SetupPanes/Settings.qml b/assets/qml/Panes/SetupPanes/Settings.qml index 686b9203..42fd1b29 100644 --- a/assets/qml/Panes/SetupPanes/Settings.qml +++ b/assets/qml/Panes/SetupPanes/Settings.qml @@ -37,7 +37,6 @@ Control { property alias startSequence: _startSequence.text property alias windowShadows: _windowShadows.checked property alias separatorSequence: _separatorSequence.text - property alias multithreadedFrameProcessing: _multithreadedFrameProcessing.checked // // Layout @@ -152,22 +151,6 @@ Control { } } - // - // Multi-threaded frame processing - // - Label { - text: qsTr("Multithreaded frame parsing") + ": " - } Switch { - id: _multithreadedFrameProcessing - Layout.leftMargin: -app.spacing - Layout.alignment: Qt.AlignLeft - checked: Cpp_JSON_Generator.processFramesInSeparateThread - onCheckedChanged: { - if (checked != Cpp_JSON_Generator.processFramesInSeparateThread) - Cpp_JSON_Generator.processFramesInSeparateThread = checked - } - } - // // Window shadows // diff --git a/src/JSON/Generator.cpp b/src/JSON/Generator.cpp index 6c464bb9..3b97a1ab 100644 --- a/src/JSON/Generator.cpp +++ b/src/JSON/Generator.cpp @@ -39,13 +39,15 @@ JSON::Generator::Generator() : m_frameCount(0) , m_opMode(kAutomatic) - , m_processInSeparateThread(false) { - const auto io = &IO::Manager::instance(); - const auto cp = &CSV::Player::instance(); - connect(cp, SIGNAL(openChanged()), this, SLOT(reset())); - connect(io, SIGNAL(deviceChanged()), this, SLOT(reset())); - connect(io, SIGNAL(frameReceived(QByteArray)), this, SLOT(readData(QByteArray))); + // clang-format off + connect(&CSV::Player::instance(), &CSV::Player::openChanged, + this, &JSON::Generator::reset); + connect(&IO::Manager::instance(), &IO::Manager::deviceChanged, + this, &JSON::Generator::reset); + connect(&IO::Manager::instance(), &IO::Manager::frameReceived, + this, &JSON::Generator::readData); + // clang-format on readSettings(); } @@ -103,14 +105,6 @@ JSON::Generator::OperationMode JSON::Generator::operationMode() const return m_opMode; } -/** - * Returns @c true if JSON frames shall be generated in a separate thread - */ -bool JSON::Generator::processFramesInSeparateThread() const -{ - return m_processInSeparateThread; -} - /** * Creates a file dialog & lets the user select the JSON file map */ @@ -203,15 +197,6 @@ void JSON::Generator::setOperationMode(const JSON::Generator::OperationMode &mod Q_EMIT operationModeChanged(); } -/** - * Enables or disables multi-threaded frame processing - */ -void JSON::Generator::setProcessFramesInSeparateThread(const bool threaded) -{ - m_processInSeparateThread = threaded; - Q_EMIT processFramesInSeparateThreadChanged(); -} - /** * Loads the last saved JSON map file (if any) */ @@ -222,25 +207,6 @@ void JSON::Generator::readSettings() loadJsonMap(path); } -/** - * Notifies the rest of the application that a new JSON frame has been received. The JFI - * also contains RX date/time and frame number. - * - * Read the "FrameInfo.h" file for more information. - */ -void JSON::Generator::loadJFI(const JFI_Object &info) -{ - const bool csvOpen = CSV::Player::instance().isOpen(); - const bool devOpen = IO::Manager::instance().connected(); - const bool mqttSub = MQTT::Client::instance().isSubscribed(); - - if (csvOpen || devOpen || mqttSub) - Q_EMIT jsonChanged(info); - - else - reset(); -} - /** * Saves the location of the last valid JSON map file that was opened (if any) */ @@ -249,16 +215,6 @@ void JSON::Generator::writeSettings(const QString &path) m_settings.setValue("json_map_location", path); } -/** - * Create a new JFI event with the given @a JSON document and increment the frame count - */ -void JSON::Generator::loadJSON(const QJsonDocument &json) -{ - m_frameCount++; - auto jfi = JFI_CreateNew(m_frameCount, QDateTime::currentDateTime(), json); - loadJFI(jfi); -} - /** * Resets all the statistics related to the current device and the JSON map file */ @@ -289,29 +245,7 @@ void JSON::Generator::readData(const QByteArray &data) // Increment received frames and process frame m_frameCount++; - - // Create new worker thread to read JSON data - if (processFramesInSeparateThread()) - { - // clang-format off - QThread *thread = new QThread; - Worker *worker = new Worker(data, - m_frameCount, - QDateTime::currentDateTime()); - worker->moveToThread(thread); - // clang-format on - - connect(thread, SIGNAL(started()), worker, SLOT(process())); - connect(worker, SIGNAL(finished()), thread, SLOT(quit())); - connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); - connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); - connect(worker, &JSON::Worker::jsonReady, this, &JSON::Generator::loadJFI); - thread->start(); - } - - // Process frames in main thread - else - processFrame(data, m_frameCount, QDateTime::currentDateTime()); + processFrame(data, m_frameCount, QDateTime::currentDateTime()); } /** @@ -321,6 +255,10 @@ void JSON::Generator::readData(const QByteArray &data) void JSON::Generator::processFrame(const QByteArray &data, const quint64 frame, const QDateTime &time) { + // + // TODO: Re-write this function because it leaks memory + // + // Serial device sends JSON (auto mode) if (operationMode() == JSON::Generator::kAutomatic) m_jfi.jsonDocument = QJsonDocument::fromJson(data, &m_error); @@ -387,97 +325,6 @@ void JSON::Generator::processFrame(const QByteArray &data, const quint64 frame, } } -//---------------------------------------------------------------------------------------- -// JSON worker object (executed for each frame on a new thread) -//---------------------------------------------------------------------------------------- - -/** - * Constructor function, stores received frame data & the date/time that the frame data - * was received. - */ -JSON::Worker::Worker(const QByteArray &data, const quint64 frame, const QDateTime &time) - : m_time(time) - , m_data(data) - , m_frame(frame) -{ -} - -/** - * Reads the frame & inserts its values on the JSON map, and/or extracts the JSON frame - * directly from the serial data. - */ -void JSON::Worker::process() -{ - // Init variables - QJsonParseError error; - QJsonDocument document; - - // Serial device sends JSON (auto mode) - if (Generator::instance().operationMode() == Generator::kAutomatic) - document = QJsonDocument::fromJson(m_data, &error); - - // We need to use a map file, check if its loaded & replace values into map - else - { - // Empty JSON map data - if (Generator::instance().jsonMapData().isEmpty()) - return; - - // Separate incoming data & add it to the JSON map - auto json = Generator::instance().jsonMapData(); - const auto sepr = IO::Manager::instance().separatorSequence(); - const auto list = QString::fromUtf8(m_data).split(sepr); - for (int i = 0; i < list.count(); ++i) - json.replace(QString("\"%%1\"").arg(i + 1), "\"" + list.at(i) + "\""); - - // Create json document - const auto jsonData = json.toUtf8(); - const auto jsonDocument = QJsonDocument::fromJson(jsonData, &error); - - // Calculate dynamically generated values - auto root = jsonDocument.object(); - auto groups = JFI_Value(root, "groups", "g").toArray(); - for (int i = 0; i < groups.count(); ++i) - { - // Get group - auto group = groups.at(i).toObject(); - - // Evaluate each dataset of the current group - auto datasets = JFI_Value(group, "datasets", "d").toArray(); - for (int j = 0; j < datasets.count(); ++j) - { - auto dataset = datasets.at(j).toObject(); - auto value = JFI_Value(dataset, "value", "v").toString(); - dataset.remove("v"); - dataset.remove("value"); - dataset.insert("value", value); - datasets.replace(j, dataset); - } - - // Replace group datasets - group.remove("d"); - group.remove("datasets"); - group.insert("datasets", datasets); - groups.replace(i, group); - } - - // Replace root document group objects - root.remove("g"); - root.remove("groups"); - root.insert("groups", groups); - - // Create JSON document - document = QJsonDocument(root); - } - - // No parse error, update UI & reset error counter - if (error.error == QJsonParseError::NoError) - Q_EMIT jsonReady(JFI_CreateNew(m_frame, m_time, document)); - - // Delete object - Q_EMIT finished(); -} - #ifdef SERIAL_STUDIO_INCLUDE_MOC # include "moc_Generator.cpp" #endif diff --git a/src/JSON/Generator.h b/src/JSON/Generator.h index 3d8b35c2..e326e115 100644 --- a/src/JSON/Generator.h +++ b/src/JSON/Generator.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -36,33 +35,6 @@ namespace JSON { -/** - * Generates a JSON document by combining the JSON map file and the received - * data from the microcontroller device. - * - * This code is executed on another thread in order to avoid blocking the - * user interface. - */ -class Worker : public QObject -{ - Q_OBJECT - -Q_SIGNALS: - void finished(); - void jsonReady(const JFI_Object &info); - -public: - Worker(const QByteArray &data, const quint64 frame, const QDateTime &time); - -public Q_SLOTS: - void process(); - -private: - QDateTime m_time; - QByteArray m_data; - quint64 m_frame; -}; - /** * @brief The Generator class * @@ -99,17 +71,12 @@ class Generator : public QObject READ operationMode WRITE setOperationMode NOTIFY operationModeChanged) - Q_PROPERTY(bool processFramesInSeparateThread - READ processFramesInSeparateThread - WRITE setProcessFramesInSeparateThread - NOTIFY processFramesInSeparateThreadChanged) // clang-format on Q_SIGNALS: void jsonFileMapChanged(); void operationModeChanged(); void jsonChanged(const JFI_Object &info); - void processFramesInSeparateThreadChanged(); private: explicit Generator(); @@ -132,19 +99,15 @@ public: QString jsonMapFilename() const; QString jsonMapFilepath() const; OperationMode operationMode() const; - bool processFramesInSeparateThread() const; public Q_SLOTS: void loadJsonMap(); void loadJsonMap(const QString &path); - void setProcessFramesInSeparateThread(const bool threaded); void setOperationMode(const JSON::Generator::OperationMode &mode); public Q_SLOTS: void readSettings(); - void loadJFI(const JFI_Object &object); void writeSettings(const QString &path); - void loadJSON(const QJsonDocument &json); private Q_SLOTS: void reset(); @@ -159,6 +122,5 @@ private: QString m_jsonMapData; OperationMode m_opMode; QJsonParseError m_error; - bool m_processInSeparateThread; }; }