Handled automation delays using condition variable.
authorG S Senthil Kumar <senthil.gs@samsung.com>
Thu, 7 Jan 2016 09:42:39 +0000 (15:12 +0530)
committerUze Choi <uzchoi@samsung.com>
Mon, 11 Jan 2016 05:16:16 +0000 (05:16 +0000)
Used condition variable instead of sleep() to introduce delay during automation.

Change-Id: I88c075a524beab60f4241baaaaae7e530a43c689
Signed-off-by: G S Senthil Kumar <senthil.gs@samsung.com>
Reviewed-on: https://gerrit.iotivity.org/gerrit/4769
Tested-by: jenkins-iotivity <jenkins-iotivity@opendaylight.org>
Reviewed-by: Uze Choi <uzchoi@samsung.com>
service/simulator/src/server/resource_update_automation.cpp
service/simulator/src/server/resource_update_automation.h
service/simulator/src/server/resource_update_automation_mngr.cpp

index 07ea8de..1c8d359 100644 (file)
@@ -28,8 +28,6 @@
 #define ATAG "ATTRIBUTE_AUTOMATION"
 #define RTAG "RESOURCE_AUTOMATION"
 
-#define SLEEP_FOR(X) if (X > 0) std::this_thread::sleep_for(std::chrono::milliseconds(X));
-
 AttributeUpdateAutomation::AttributeUpdateAutomation(int id, SimulatorSingleResource *resource,
         const SimulatorResourceModel::Attribute &attribute, AutomationType type, int interval,
         updateCompleteCallback callback, std::function<void (const int)> finishedCallback)
@@ -49,15 +47,26 @@ AttributeUpdateAutomation::AttributeUpdateAutomation(int id, SimulatorSingleReso
     }
 }
 
+AttributeUpdateAutomation::~AttributeUpdateAutomation()
+{
+    if(!m_stopRequested)
+        m_thread->detach();
+}
+
 void AttributeUpdateAutomation::start()
 {
-    m_thread = std::make_shared<std::thread>(&AttributeUpdateAutomation::updateAttribute, this);
-    m_thread->detach();
+    m_thread.reset(new std::thread(&AttributeUpdateAutomation::updateAttribute, this));
 }
 
 void AttributeUpdateAutomation::stop()
 {
-    m_stopRequested = true;
+    {
+        std::lock_guard<std::mutex> lock(m_lock);
+        m_stopRequested = true;
+    }
+    m_condVariable.notify_one();
+    if(m_thread)
+        m_thread->join();
 }
 
 void AttributeUpdateAutomation::updateAttribute()
@@ -68,6 +77,8 @@ void AttributeUpdateAutomation::updateAttribute()
     if (!resourceImpl)
         return;
 
+    std::unique_lock<std::mutex> lock(m_lock);
+    std::chrono::system_clock::time_point now;
     do
     {
         try
@@ -87,7 +98,9 @@ void AttributeUpdateAutomation::updateAttribute()
 
                 resourceImpl->notifyApp();
 
-                SLEEP_FOR(m_updateInterval);
+                now = std::chrono::system_clock::now();
+                m_condVariable.wait_until(lock, now + std::chrono::milliseconds(m_updateInterval),
+                    [this]{ return m_stopRequested; });
             }
 
             m_attributeGen.reset();
@@ -109,8 +122,11 @@ void AttributeUpdateAutomation::updateAttribute()
     if (m_callback)
         m_callback(m_resource->getURI(), m_id);
 
-    if (m_finishedCallback)
-        m_finishedCallback(m_id);
+    if (m_finishedCallback && !m_stopRequested)
+    {
+        std::thread notifyManager(m_finishedCallback, m_id);
+        notifyManager.detach();
+    }
 }
 
 ResourceUpdateAutomation::ResourceUpdateAutomation(int id, SimulatorSingleResource *resource,
@@ -125,6 +141,12 @@ ResourceUpdateAutomation::ResourceUpdateAutomation(int id, SimulatorSingleResour
         m_finishedCallback(finishedCallback),
         m_thread(nullptr) {}
 
+ResourceUpdateAutomation::~ResourceUpdateAutomation()
+{
+    if(!m_stopRequested)
+        m_thread->detach();
+}
+
 void ResourceUpdateAutomation::start()
 {
     std::vector<SimulatorResourceModel::Attribute> attributes;
@@ -139,13 +161,18 @@ void ResourceUpdateAutomation::start()
         throw SimulatorException(SIMULATOR_ERROR, "Resource has zero attributes!");
     }
 
-    m_thread = std::make_shared<std::thread>(&ResourceUpdateAutomation::updateAttributes, this, attributes);
-    m_thread->detach();
+    m_thread.reset(new std::thread(&ResourceUpdateAutomation::updateAttributes, this, attributes));
 }
 
 void ResourceUpdateAutomation::stop()
 {
-    m_stopRequested = true;
+    {
+        std::lock_guard<std::mutex> lock(m_lock);
+        m_stopRequested = true;
+    }
+    m_condVariable.notify_one();
+    if(m_thread)
+        m_thread->join();
 }
 
 void ResourceUpdateAutomation::updateAttributes(
@@ -157,6 +184,8 @@ void ResourceUpdateAutomation::updateAttributes(
     if (!resourceImpl)
         return;
 
+    std::unique_lock<std::mutex> lock(m_lock);
+    std::chrono::system_clock::time_point now;
     do
     {
         AttributeCombinationGen attrCombGen(attributes);
@@ -173,7 +202,11 @@ void ResourceUpdateAutomation::updateAttributes(
             }
 
             resourceImpl->notifyApp();
-            SLEEP_FOR(m_updateInterval);
+
+            now = std::chrono::system_clock::now();
+            m_condVariable.wait_until(lock, now + std::chrono::milliseconds(m_updateInterval),
+                [this]{ return m_stopRequested; });
+
         }
     }
     while (!m_stopRequested && AutomationType::RECURRENT == m_type);
@@ -187,7 +220,10 @@ void ResourceUpdateAutomation::updateAttributes(
     if (m_callback)
         m_callback(m_resource->getURI(), m_id);
 
-    if (m_finishedCallback)
-        m_finishedCallback(m_id);
+    if (m_finishedCallback && !m_stopRequested)
+    {
+        std::thread notifyManager(m_finishedCallback, m_id);
+        notifyManager.detach();
+    }
 }
 
index 54263bf..5a979df 100644 (file)
@@ -24,6 +24,8 @@
 #include "simulator_single_resource.h"
 #include "attribute_generator.h"
 #include <thread>
+#include <condition_variable>
+#include <atomic>
 
 class AttributeUpdateAutomation
 {
@@ -34,6 +36,8 @@ class AttributeUpdateAutomation
                                   updateCompleteCallback callback,
                                   std::function<void (const int)> finishedCallback);
 
+        ~AttributeUpdateAutomation();
+
         void start();
 
         void stop();
@@ -50,7 +54,10 @@ class AttributeUpdateAutomation
         AttributeGenerator m_attributeGen;
         updateCompleteCallback m_callback;
         std::function<void (const int)> m_finishedCallback;
-        std::shared_ptr<std::thread> m_thread;
+        std::unique_ptr<std::thread> m_thread;
+
+        std::mutex m_lock;
+        std::condition_variable m_condVariable;
 };
 
 typedef std::shared_ptr<AttributeUpdateAutomation> AttributeUpdateAutomationSP;
@@ -63,6 +70,8 @@ class ResourceUpdateAutomation
                                  updateCompleteCallback callback,
                                  std::function<void (const int)> finishedCallback);
 
+        ~ResourceUpdateAutomation();
+
         void start();
 
         void stop();
@@ -77,7 +86,10 @@ class ResourceUpdateAutomation
         int m_updateInterval;
         updateCompleteCallback m_callback;
         std::function<void (const int)> m_finishedCallback;
-        std::shared_ptr<std::thread> m_thread;
+        std::unique_ptr<std::thread> m_thread;
+
+        std::mutex m_lock;
+        std::condition_variable m_condVariable;
 };
 
 typedef std::shared_ptr<ResourceUpdateAutomation> ResourceUpdateAutomationSP;
index 972b176..1b52c70 100644 (file)
@@ -112,11 +112,13 @@ void UpdateAutomationMngr::stop(int id)
     if (m_resourceUpdationList.end() != m_resourceUpdationList.find(id))
     {
         m_resourceUpdationList[id]->stop();
+        m_resourceUpdationList.erase(m_resourceUpdationList.find(id));
         return;
     }
     else if (m_attrUpdationList.end() != m_attrUpdationList.find(id))
     {
         m_attrUpdationList[id]->stop();
+        m_attrUpdationList.erase(m_attrUpdationList.find(id));
         return;
     }
 }