From 348a7ffdbb90a39825dafb47978610ded1239798 Mon Sep 17 00:00:00 2001
From: phesch <ulila@student.kit.edu>
Date: Fri, 29 Apr 2022 21:16:37 +0200
Subject: [PATCH] Fix MemoryGUI timer starting and stopping.

---
 .../armem_gui/PeriodicUpdateWidget.cpp        | 31 ++++++++++++++-----
 .../armem_gui/PeriodicUpdateWidget.h          |  5 ++-
 2 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.cpp b/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.cpp
index 2e315e6f0..3c3b262ba 100644
--- a/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.cpp
+++ b/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.cpp
@@ -8,7 +8,6 @@
 
 #include <cmath>
 
-
 namespace armarx::armem::gui
 {
 
@@ -51,6 +50,10 @@ namespace armarx::armem::gui
 
         connect(this, &This::updateSingle, this, &This::update);
         connect(this, &This::updatePeriodic, this, &This::update);
+
+        // See `startTimerIfEnabled` for the signal reasoning.
+        connect(this, &This::startTimerSignal, this, &This::_startTimerSlot);
+        connect(this, &This::stopTimerSignal, this, &This::_stopTimerSlot);
     }
 
     QPushButton* PeriodicUpdateWidget::updateButton()
@@ -66,22 +69,25 @@ namespace armarx::armem::gui
 
     void PeriodicUpdateWidget::startTimerIfEnabled()
     {
+        /* A QTimer can only be started and stopped within its own thread (the thread for which
+         * it has the greatest affinity). Since this method can be called from any thread, we
+         * need to take a detour through these signals, which can be emitted from any thread and
+         * will always be caught in this object's (and thus the timer's) native thread.
+         */
         if (_autoCheckBox->isChecked())
         {
-            _timer->start();
+            emit startTimerSignal();
         }
         else
         {
-            _timer->stop();
+            emit stopTimerSignal();
         }
     }
 
     void PeriodicUpdateWidget::stopTimer()
     {
-        if (_timer)
-        {
-            _timer->stop();
-        }
+        // See `startTimerIfEnabled` for the signal reasoning.
+        emit stopTimerSignal();
     }
 
     void PeriodicUpdateWidget::_updateTimerFrequency()
@@ -91,6 +97,7 @@ namespace armarx::armem::gui
 
     void PeriodicUpdateWidget::_toggleAutoUpdates(bool enabled)
     {
+        // This method is already a slot, so it doesn't need to use the timer signals.
         _frequencySpinBox->setEnabled(enabled);
         if (enabled)
         {
@@ -102,6 +109,16 @@ namespace armarx::armem::gui
         }
     }
 
+    void PeriodicUpdateWidget::_startTimerSlot()
+    {
+        _timer->start();
+    }
+
+    void PeriodicUpdateWidget::_stopTimerSlot()
+    {
+        _timer->stop();
+    }
+
     QCheckBox* PeriodicUpdateWidget::autoCheckBox()
     {
         return _autoCheckBox;
diff --git a/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.h b/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.h
index db8d9d5a3..d99c20f67 100644
--- a/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.h
+++ b/source/RobotAPI/libraries/armem_gui/PeriodicUpdateWidget.h
@@ -49,11 +49,14 @@ namespace armarx::armem::gui
 
         void _updateTimerFrequency();
         void _toggleAutoUpdates(bool enabled);
+        void _startTimerSlot();
+        void _stopTimerSlot();
 
 
     signals:
 
-
+        void startTimerSignal();
+        void stopTimerSignal();
 
     private:
 
-- 
GitLab