NVMeBasicContext: Poll all sensors each polling interval

Rework the polling protocol so that the completion of polling sensor N
invokes polling of sensor N+1 for the given context.

The timer is retained in order to trigger polling the initial sensor.

Signed-off-by: Andrew Jeffery <andrew@aj.id.au>
Change-Id: I599547c8c790905549c0cad9fbfbe63cf6930de4
diff --git a/include/NVMeBasicContext.hpp b/include/NVMeBasicContext.hpp
index 29b55d9..6b0a425 100644
--- a/include/NVMeBasicContext.hpp
+++ b/include/NVMeBasicContext.hpp
@@ -11,8 +11,10 @@
     NVMeBasicContext(boost::asio::io_service& io, int rootBus);
     ~NVMeBasicContext() override = default;
     void pollNVMeDevices() override;
-    void readAndProcessNVMeSensor() override;
-    void processResponse(void* msg, size_t len) override;
+    void readAndProcessNVMeSensor(
+        std::list<std::shared_ptr<NVMeSensor>>::iterator iter) override;
+    void processResponse(std::shared_ptr<NVMeSensor>& sensor, void* msg,
+                         size_t len) override;
 
   private:
     NVMeBasicContext(boost::asio::io_service& io, int rootBus, int cmdOut,
diff --git a/include/NVMeContext.hpp b/include/NVMeContext.hpp
index f8270f2..2489815 100644
--- a/include/NVMeContext.hpp
+++ b/include/NVMeContext.hpp
@@ -50,22 +50,18 @@
         sensors.remove(sensor);
     }
 
-    virtual void pollNVMeDevices()
-    {}
-
     virtual void close()
     {
         scanTimer.cancel();
     }
 
-    virtual void readAndProcessNVMeSensor()
-    {}
+    virtual void pollNVMeDevices() = 0;
 
-    virtual void processResponse(void* msg, size_t len)
-    {
-        (void)msg;
-        (void)len;
-    }
+    virtual void readAndProcessNVMeSensor(
+        std::list<std::shared_ptr<NVMeSensor>>::iterator iter) = 0;
+
+    virtual void processResponse(std::shared_ptr<NVMeSensor>& sensor, void* msg,
+                                 size_t len) = 0;
 
   protected:
     boost::asio::deadline_timer scanTimer;
diff --git a/src/NVMeBasicContext.cpp b/src/NVMeBasicContext.cpp
index dacac26..c755e23 100644
--- a/src/NVMeBasicContext.cpp
+++ b/src/NVMeBasicContext.cpp
@@ -244,19 +244,22 @@
     thread.detach();
 }
 
-void NVMeBasicContext::readAndProcessNVMeSensor()
+void NVMeBasicContext::readAndProcessNVMeSensor(
+    std::list<std::shared_ptr<NVMeSensor>>::iterator iter)
 {
-    if (sensors.empty())
+    if (iter == sensors.end())
     {
+        this->pollNVMeDevices();
         return;
     }
 
-    std::shared_ptr<NVMeSensor>& sensor = sensors.front();
+    std::shared_ptr<NVMeSensor> sensor = *iter++;
 
     if (!sensor->readingStateGood())
     {
         sensor->markAvailable(false);
         sensor->updateValue(std::numeric_limits<double>::quiet_NaN());
+        readAndProcessNVMeSensor(iter);
         return;
     }
 
@@ -314,8 +317,8 @@
             response->prepare(len);
             return len;
         },
-        [self{shared_from_this()},
-         response](const boost::system::error_code& ec, std::size_t length) {
+        [self{shared_from_this()}, iter, sensor, response](
+            const boost::system::error_code& ec, std::size_t length) mutable {
             if (ec)
             {
                 std::cerr << "Got error reading basic query: " << ec << "\n";
@@ -340,29 +343,34 @@
             std::vector<char> data(response->size());
             is.read(data.data(), response->size());
 
-            self->processResponse(data.data(), data.size());
+            /* Update the sensor */
+            self->processResponse(sensor, data.data(), data.size());
+
+            /* Enqueue processing of the next sensor */
+            self->readAndProcessNVMeSensor(iter);
         });
 }
 
 void NVMeBasicContext::pollNVMeDevices()
 {
+    auto scan = sensors.begin();
+
     scanTimer.expires_from_now(boost::posix_time::seconds(1));
-    scanTimer.async_wait(
-        [self{shared_from_this()}](const boost::system::error_code errorCode) {
-            if (errorCode == boost::asio::error::operation_aborted)
-            {
-                return;
-            }
+    scanTimer.async_wait([self{shared_from_this()},
+                          scan](const boost::system::error_code errorCode) {
+        if (errorCode == boost::asio::error::operation_aborted)
+        {
+            return;
+        }
 
-            if (errorCode)
-            {
-                std::cerr << errorCode.message() << "\n";
-                return;
-            }
+        if (errorCode)
+        {
+            std::cerr << errorCode.message() << "\n";
+            return;
+        }
 
-            self->readAndProcessNVMeSensor();
-            self->pollNVMeDevices();
-        });
+        self->readAndProcessNVMeSensor(scan);
+    });
 }
 
 static double getTemperatureReading(int8_t reading)
@@ -378,7 +386,8 @@
     return reading;
 }
 
-void NVMeBasicContext::processResponse(void* msg, size_t len)
+void NVMeBasicContext::processResponse(std::shared_ptr<NVMeSensor>& sensor,
+                                       void* msg, size_t len)
 {
     if (msg == nullptr)
     {
@@ -393,8 +402,6 @@
     }
 
     uint8_t* messageData = static_cast<uint8_t*>(msg);
-
-    std::shared_ptr<NVMeSensor> sensor = sensors.front();
     double value = getTemperatureReading(messageData[2]);
 
     if (std::isfinite(value))
@@ -406,7 +413,4 @@
         sensor->markAvailable(false);
         sensor->incrementError();
     }
-
-    sensors.pop_front();
-    sensors.emplace_back(sensor);
 }