From f63f72618e63a90d1f1da93e7972eb6dd6d904c7 Mon Sep 17 00:00:00 2001
From: Raphael Grimm <raphael.grimm@kit.edu>
Date: Wed, 25 Apr 2018 08:18:06 +0200
Subject: [PATCH] Fix RobotUnitGui hanging when RobotUnit is running on a
 different pc

---
 .../QWidgets/ControlDevicesWidget.cpp              | 12 ++++++++----
 .../QWidgets/NJointControllerClassesWidget.cpp     |  6 +++---
 .../QWidgets/NJointControllersWidget.cpp           | 14 +++++++++-----
 .../QWidgets/RobotUnitWidgetBase.cpp               |  6 +++---
 .../RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.h |  2 +-
 .../QWidgets/SensorDevicesWidget.cpp               | 10 +++++++---
 6 files changed, 31 insertions(+), 19 deletions(-)

diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/ControlDevicesWidget.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/ControlDevicesWidget.cpp
index 9bedd0780..84521faef 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/ControlDevicesWidget.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/ControlDevicesWidget.cpp
@@ -70,7 +70,11 @@ namespace armarx
 
     void ControlDevicesWidget::controlDeviceStatusChanged(const ControlDeviceStatus& status)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex, std::defer_lock};
+        if (!guard.try_lock_for(std::chrono::microseconds(100)))
+        {
+            return;
+        }
         if (statusUpdates[status.deviceName].timestampUSec < status.timestampUSec)
         {
             statusUpdates[status.deviceName] = status;
@@ -98,7 +102,7 @@ namespace armarx
     {
         auto temp = robotUnit->getControlDeviceDescriptions();
         {
-            std::lock_guard<std::recursive_mutex> guard {mutex};
+            std::unique_lock<std::recursive_timed_mutex> guard {mutex};
             resetData = std::move(temp);
         }
     }
@@ -116,7 +120,7 @@ namespace armarx
 
     void ControlDevicesWidget::add(const ControlDeviceDescription& desc)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (entries.count(desc.deviceName))
         {
             return;
@@ -126,7 +130,7 @@ namespace armarx
 
     void ControlDevicesWidget::update(const ControlDeviceStatus& status)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (!robotUnit || ! robotUnit->isRunning())
         {
             return;
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllerClassesWidget.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllerClassesWidget.cpp
index 03ce425d2..f4462a470 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllerClassesWidget.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllerClassesWidget.cpp
@@ -90,7 +90,7 @@ namespace armarx
     void NJointControllerClassesWidget::nJointControllerClassAdded(std::string name)
     {
         RobotUnitInterfacePrx ru;
-        std::unique_lock<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (!robotUnit)
         {
             return;
@@ -155,7 +155,7 @@ namespace armarx
     {
         auto temp = robotUnit->getNJointControllerClassDescriptions();
         {
-            std::lock_guard<std::recursive_mutex> guard {mutex};
+            std::unique_lock<std::recursive_timed_mutex> guard {mutex};
             for (NJointControllerClassDescription& ds : temp)
             {
                 nJointControllerClassDescriptions[ds.className] = std::move(ds);
@@ -216,7 +216,7 @@ namespace armarx
 
     void NJointControllerClassesWidget::add(const  NJointControllerClassDescription& desc)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (entries.count(desc.className))
         {
             return;
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllersWidget.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllersWidget.cpp
index d0289b8ae..554ee4780 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllersWidget.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/NJointControllersWidget.cpp
@@ -89,7 +89,11 @@ namespace armarx
 
     void NJointControllersWidget::nJointControllerStatusChanged(const NJointControllerStatus& status)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex, std::defer_lock};
+        if (!guard.try_lock_for(std::chrono::microseconds(100)))
+        {
+            return;
+        }
         if (statusUpdates[status.instanceName].timestampUSec < status.timestampUSec)
         {
             statusUpdates[status.instanceName] = status;
@@ -108,7 +112,7 @@ namespace armarx
 
     void NJointControllersWidget::onPushButtonStopAll_clicked()
     {
-        if(robotUnit)
+        if (robotUnit)
         {
             robotUnit->switchNJointControllerSetup({});
         }
@@ -133,7 +137,7 @@ namespace armarx
     void NJointControllersWidget::nJointControllerCreated(std::string name)
     {
         RobotUnitInterfacePrx ru;
-        std::unique_lock<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (isResetting || !robotUnit || entries.count(name))
         {
             return;
@@ -151,7 +155,7 @@ namespace armarx
 
     void NJointControllersWidget::nJointControllerDeleted(std::string name)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         controllersDeleted.emplace(name);
         QMetaObject::invokeMethod(this, "updateContent", Qt::QueuedConnection);
     }
@@ -226,7 +230,7 @@ namespace armarx
     {
         auto temp = robotUnit->getNJointControllerDescriptionsWithStatuses();
         {
-            std::lock_guard<std::recursive_mutex> guard {mutex};
+            std::unique_lock<std::recursive_timed_mutex> guard {mutex};
             for (NJointControllerDescriptionWithStatus& ds : temp)
             {
                 controllersCreated[ds.description.instanceName] = std::move(ds);
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.cpp
index 995cfff50..f4b419b4b 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.cpp
@@ -39,7 +39,7 @@ namespace armarx
         {
             return;
         }
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         resetCount = 0;
         getResettigLabel().setText("Resetting... " + QString::number(resetCount));
         getStackedWidget().setCurrentIndex(0);
@@ -54,14 +54,14 @@ namespace armarx
     {
         isResetting = true;
         gotResetData = false;
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         robotUnit = ru;
         QMetaObject::invokeMethod(this, "doReset", Qt::QueuedConnection);
     }
 
     void RobotUnitWidgetBase::doReset()
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         clearAll();
         getTreeWidget().clear();
         addFilter();
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.h b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.h
index 7a6a122a0..09ab24e9e 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.h
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/RobotUnitWidgetBase.h
@@ -75,7 +75,7 @@ namespace armarx
         void timerEvent(QTimerEvent*) override;
 
         RobotUnitInterfacePrx robotUnit;
-        mutable std::recursive_mutex mutex;
+        mutable std::recursive_timed_mutex mutex;
         std::atomic_bool gotResetData {false};
         int resetTimerId {0};
         int resetCount {0};
diff --git a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/SensorDevicesWidget.cpp b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/SensorDevicesWidget.cpp
index a6ff6b745..87ed1e20e 100644
--- a/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/SensorDevicesWidget.cpp
+++ b/source/RobotAPI/gui-plugins/RobotUnitPlugin/QWidgets/SensorDevicesWidget.cpp
@@ -54,7 +54,11 @@ namespace armarx
 
     void SensorDevicesWidget::sensorDeviceStatusChanged(const SensorDeviceStatus& status)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex, std::defer_lock};
+        if (!guard.try_lock_for(std::chrono::microseconds(100)))
+        {
+            return;
+        }
         if (statusUpdates[status.deviceName].timestampUSec < status.timestampUSec)
         {
             statusUpdates[status.deviceName] = status;
@@ -86,7 +90,7 @@ namespace armarx
     {
         auto temp = robotUnit->getSensorDeviceDescriptions();
         {
-            std::lock_guard<std::recursive_mutex> guard {mutex};
+            std::unique_lock<std::recursive_timed_mutex> guard {mutex};
             resetData = std::move(temp);
         }
     }
@@ -104,7 +108,7 @@ namespace armarx
 
     void SensorDevicesWidget::add(const SensorDeviceDescription& desc)
     {
-        std::lock_guard<std::recursive_mutex> guard {mutex};
+        std::unique_lock<std::recursive_timed_mutex> guard {mutex};
         if (!entries.count(desc.deviceName))
         {
             entries[desc.deviceName] = new SensorDevicesWidgetEntry(*this, *(ui->treeWidget), desc);
-- 
GitLab