From f03fca85aa7960b6d9bf7205412f62ea94d141fc Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Sat, 6 Jun 2020 15:14:08 +0200 Subject: [PATCH] add thread priority option (using QThread) --- forms/advanced-scene-switcher.ui | 9 ++++- src/advanced-scene-switcher.cpp | 33 ++++++++++++---- src/general.cpp | 2 +- src/headers/advanced-scene-switcher.hpp | 1 + src/headers/switcher-data-structs.hpp | 36 ++++++++++++------ src/hotkey.cpp | 6 +-- src/priority.cpp | 50 ++++++++++++++++++------- 7 files changed, 101 insertions(+), 36 deletions(-) diff --git a/forms/advanced-scene-switcher.ui b/forms/advanced-scene-switcher.ui index 17cad277..f31dbbf8 100644 --- a/forms/advanced-scene-switcher.ui +++ b/forms/advanced-scene-switcher.ui @@ -348,7 +348,7 @@ - Use thread priority (experimental) + Use thread priority @@ -368,6 +368,13 @@ + + + + (raising the priority higher than "Normal" is usually not recommended) + + + diff --git a/src/advanced-scene-switcher.cpp b/src/advanced-scene-switcher.cpp index fe3a7fe6..7177656f 100644 --- a/src/advanced-scene-switcher.cpp +++ b/src/advanced-scene-switcher.cpp @@ -353,7 +353,7 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) ui->readPathLineEdit->setDisabled(true); } - if (switcher->th.joinable()) + if (switcher->th && switcher->th->isRunning()) SetStarted(); else SetStopped(); @@ -400,8 +400,17 @@ SceneSwitcher::SceneSwitcher(QWidget *parent) item->setData(Qt::UserRole, text); } - for (std::string p : switcher->threadPrioritiesNamesOrderdByPrio) { - ui->threadPriority->addItem(p.c_str()); + for (int i = 0; i < switcher->threadPriorities.size(); ++i) { + ui->threadPriority->addItem( + switcher->threadPriorities[i].name.c_str()); + ui->threadPriority->setItemData( + i, switcher->threadPriorities[i].description.c_str(), + Qt::ToolTipRole); + if (switcher->threadPriority == + switcher->threadPriorities[i].value) { + ui->threadPriority->setCurrentText( + switcher->threadPriorities[i].name.c_str()); + } } } @@ -882,6 +891,9 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) obs_data_set_int(obj, "priority7", switcher->functionNamesByPriority[7]); + obs_data_set_int(obj, "threadPriority", + switcher->threadPriority); + obs_data_set_obj(save_data, "advanced-scene-switcher", obj); obs_data_array_release(array); @@ -1362,6 +1374,11 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *) (DEFAULT_PRIORITY_7); } + obs_data_set_default_int(obj, "threadPriority", + QThread::NormalPriority); + switcher->threadPriority = + obs_data_get_int(obj, "threadPriority"); + obs_data_array_release(array); obs_data_array_release(screenRegionArray); obs_data_array_release(pauseScenesArray); @@ -1544,19 +1561,21 @@ bool SwitcherData::sceneChangedDuringWait() void SwitcherData::Start() { - if (!th.joinable()) { + if (!(th && th->isRunning())) { stop = false; - switcher->th = thread([]() { switcher->Thread(); }); + switcher->th = QThread::create([]() { switcher->Thread(); }); + switcher->th->start((QThread::Priority)switcher->threadPriority); } } + void SwitcherData::Stop() { - if (th.joinable()) { + if (th && th->isRunning()) { switcher->stop = true; transitionCv.notify_one(); cv.notify_one(); - th.join(); + th->wait(); } } diff --git a/src/general.cpp b/src/general.cpp index 3fe65e72..9bc85203 100644 --- a/src/general.cpp +++ b/src/general.cpp @@ -89,7 +89,7 @@ void SceneSwitcher::SetStopped() void SceneSwitcher::on_toggleStartButton_clicked() { - if (switcher->th.joinable()) + if (switcher->th && switcher->th->isRunning()) { switcher->Stop(); SetStopped(); diff --git a/src/headers/advanced-scene-switcher.hpp b/src/headers/advanced-scene-switcher.hpp index 16ddd5be..e11e548e 100644 --- a/src/headers/advanced-scene-switcher.hpp +++ b/src/headers/advanced-scene-switcher.hpp @@ -130,6 +130,7 @@ public slots: void on_priorityUp_clicked(); void on_priorityDown_clicked(); + void on_threadPriority_currentTextChanged(const QString &text); void updateScreenRegionCursorPos(); diff --git a/src/headers/switcher-data-structs.hpp b/src/headers/switcher-data-structs.hpp index 94a0c3b3..2a12d6ef 100644 --- a/src/headers/switcher-data-structs.hpp +++ b/src/headers/switcher-data-structs.hpp @@ -3,7 +3,6 @@ #include #include #include -#include #include #include #include @@ -256,7 +255,7 @@ typedef enum { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 } NoMatch; * SwitcherData ********************************************************************************/ struct SwitcherData { - thread th; + QThread* th = nullptr; condition_variable cv; mutex m; bool transitionActive = false; @@ -311,18 +310,33 @@ struct SwitcherData { DEFAULT_PRIORITY_3, DEFAULT_PRIORITY_4, DEFAULT_PRIORITY_5, DEFAULT_PRIORITY_6, DEFAULT_PRIORITY_7}; - std::vector threadPrioritiesNamesOrderdByPrio{ - "Lowest", "Low", "Normal", "High", "Highest", "Time critical", + struct ThreadPrio { + std::string name; + std::string description; + uint32_t value; }; - std::map threadPriorities = { - {"Lowest", QThread::LowestPriority}, - {"Low", QThread::LowPriority}, - {"Normal", QThread::NormalPriority}, - {"High", QThread::HighPriority}, - {"Highest", QThread::HighestPriority}, - {"Time critical", QThread::TimeCriticalPriority}, + + std::vector threadPriorities{ + {"Idle", + "scheduled only when no other threads are running (lowest CPU load)", + QThread::IdlePriority}, + {"Lowest", "scheduled less often than LowPriority", + QThread::LowestPriority}, + {"Low", "scheduled less often than NormalPriority", + QThread::LowPriority}, + {"Normal", "the default priority of the operating system", + QThread::NormalPriority}, + {"High", "scheduled more often than NormalPriority", + QThread::HighPriority}, + {"Highest", "scheduled more often than HighPriority", + QThread::HighestPriority}, + {"Time critical", + "scheduled as often as possible (highest CPU load)", + QThread::TimeCriticalPriority}, }; + uint32_t threadPriority = QThread::NormalPriority; + void Thread(); void Start(); void Stop(); diff --git a/src/hotkey.cpp b/src/hotkey.cpp index 924eedbb..f95b5773 100644 --- a/src/hotkey.cpp +++ b/src/hotkey.cpp @@ -8,7 +8,7 @@ void startHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pr if (pressed) { - if (!switcher->th.joinable()) + if (!(switcher->th && switcher->th->isRunning())) switcher->Start(); } @@ -43,7 +43,7 @@ void stopHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotkey, bool pre if (pressed) { - if (switcher->th.joinable()) + if (switcher->th && switcher->th->isRunning()) switcher->Stop(); } @@ -78,7 +78,7 @@ void startStopToggleHotkeyFunc(void* data, obs_hotkey_id id, obs_hotkey_t* hotke if (pressed) { - if (switcher->th.joinable()) + if (switcher->th && switcher->th->isRunning()) switcher->Stop(); else switcher->Start(); diff --git a/src/priority.cpp b/src/priority.cpp index 22019b9c..60f5e30e 100644 --- a/src/priority.cpp +++ b/src/priority.cpp @@ -1,44 +1,68 @@ #include #include "headers/advanced-scene-switcher.hpp" +void SceneSwitcher::on_threadPriority_currentTextChanged(const QString &text) +{ + if (loading || ui->threadPriority->count() != switcher->threadPriorities.size()) + return; + + lock_guard lock(switcher->m); + + for (auto p : switcher->threadPriorities) { + if (p.name == text.toUtf8() + .constData()) { + switcher->threadPriority = p.value; + break; + } + } +} + void SceneSwitcher::on_priorityUp_clicked() { int currentIndex = ui->priorityList->currentRow(); - if (currentIndex != -1 && currentIndex != 0) - { - ui->priorityList->insertItem(currentIndex - 1 ,ui->priorityList->takeItem(currentIndex)); - ui->priorityList->setCurrentRow(currentIndex -1); + if (currentIndex != -1 && currentIndex != 0) { + ui->priorityList->insertItem( + currentIndex - 1, + ui->priorityList->takeItem(currentIndex)); + ui->priorityList->setCurrentRow(currentIndex - 1); lock_guard lock(switcher->m); - iter_swap(switcher->functionNamesByPriority.begin() + currentIndex, switcher->functionNamesByPriority.begin() + currentIndex - 1); + iter_swap(switcher->functionNamesByPriority.begin() + + currentIndex, + switcher->functionNamesByPriority.begin() + + currentIndex - 1); } } void SceneSwitcher::on_priorityDown_clicked() { int currentIndex = ui->priorityList->currentRow(); - if (currentIndex != -1 && currentIndex != ui->priorityList->count() - 1) - { - ui->priorityList->insertItem(currentIndex + 1, ui->priorityList->takeItem(currentIndex)); + if (currentIndex != -1 && + currentIndex != ui->priorityList->count() - 1) { + ui->priorityList->insertItem( + currentIndex + 1, + ui->priorityList->takeItem(currentIndex)); ui->priorityList->setCurrentRow(currentIndex + 1); lock_guard lock(switcher->m); - iter_swap(switcher->functionNamesByPriority.begin() + currentIndex, switcher->functionNamesByPriority.begin() + currentIndex + 1); + iter_swap(switcher->functionNamesByPriority.begin() + + currentIndex, + switcher->functionNamesByPriority.begin() + + currentIndex + 1); } } bool SwitcherData::prioFuncsValid() { - auto it = std::unique(functionNamesByPriority.begin(), functionNamesByPriority.end()); + auto it = std::unique(functionNamesByPriority.begin(), + functionNamesByPriority.end()); bool wasUnique = (it == functionNamesByPriority.end()); if (!wasUnique) return false; - for (int p : functionNamesByPriority) - { + for (int p : functionNamesByPriority) { if (p < 0 || p > 7) return false; } return true; } -