diff --git a/include/NVMeBasicContext.hpp b/include/NVMeBasicContext.hpp index 6953dd784..ec7a0b108 100644 --- a/include/NVMeBasicContext.hpp +++ b/include/NVMeBasicContext.hpp @@ -11,8 +11,7 @@ class NVMeBasicContext : public NVMeContext NVMeBasicContext(boost::asio::io_service& io, int rootBus); ~NVMeBasicContext() override = default; void pollNVMeDevices() override; - void readAndProcessNVMeSensor( - std::list>::iterator iter) override; + void readAndProcessNVMeSensor() override; void processResponse(std::shared_ptr& sensor, void* msg, size_t len) override; diff --git a/include/NVMeContext.hpp b/include/NVMeContext.hpp index 24898159f..230ca74f7 100644 --- a/include/NVMeContext.hpp +++ b/include/NVMeContext.hpp @@ -12,7 +12,7 @@ class NVMeContext : public std::enable_shared_from_this { public: NVMeContext(boost::asio::io_service& io, int rootBus) : - scanTimer(io), rootBus(rootBus) + scanTimer(io), rootBus(rootBus), pollCursor(sensors.end()) { if (rootBus < 0) { @@ -45,9 +45,44 @@ class NVMeContext : public std::enable_shared_from_this return std::nullopt; } + // Post-condition: The sensor list does not contain the provided sensor + // Post-condition: pollCursor is a valid iterator for the sensor list void removeSensor(const std::shared_ptr& sensor) { - sensors.remove(sensor); + // Locate the sensor that we're removing in the sensor list + auto found = std::find(sensors.begin(), sensors.end(), sensor); + + // If we failed to find the sensor in the list the post-condition is + // already satisfied + if (found == sensors.end()) + { + return; + } + + // We've found the sensor in the list + + // If we're not actively polling the sensor list, then remove the sensor + if (pollCursor == sensors.end()) + { + sensors.erase(found); + return; + } + + // We're actively polling the sensor list + + // If we're not polling the specific sensor that has been removed, then + // remove the sensor + if (*pollCursor != *found) + { + sensors.erase(found); + return; + } + + // We're polling the sensor that is being removed + + // Remove the sensor and update the poll cursor so the cursor remains + // valid + pollCursor = sensors.erase(found); } virtual void close() @@ -57,16 +92,16 @@ class NVMeContext : public std::enable_shared_from_this virtual void pollNVMeDevices() = 0; - virtual void readAndProcessNVMeSensor( - std::list>::iterator iter) = 0; + virtual void readAndProcessNVMeSensor() = 0; virtual void processResponse(std::shared_ptr& sensor, void* msg, size_t len) = 0; protected: boost::asio::deadline_timer scanTimer; - int rootBus; // Root bus for this drive - std::list> sensors; // used as a poll queue + int rootBus; // Root bus for this drive + std::list> sensors; + std::list>::iterator pollCursor; }; using NVMEMap = boost::container::flat_map>; diff --git a/src/NVMeBasicContext.cpp b/src/NVMeBasicContext.cpp index 5708ad843..d0ece2c60 100644 --- a/src/NVMeBasicContext.cpp +++ b/src/NVMeBasicContext.cpp @@ -246,29 +246,28 @@ NVMeBasicContext::NVMeBasicContext(boost::asio::io_service& io, int rootBus) : thread.detach(); } -void NVMeBasicContext::readAndProcessNVMeSensor( - std::list>::iterator iter) +void NVMeBasicContext::readAndProcessNVMeSensor() { - if (iter == sensors.end()) + if (pollCursor == sensors.end()) { this->pollNVMeDevices(); return; } - std::shared_ptr sensor = *iter++; + std::shared_ptr sensor = *pollCursor++; if (!sensor->readingStateGood()) { sensor->markAvailable(false); sensor->updateValue(std::numeric_limits::quiet_NaN()); - readAndProcessNVMeSensor(iter); + readAndProcessNVMeSensor(); return; } /* Potentially defer sampling the sensor sensor if it is in error */ if (!sensor->sample()) { - readAndProcessNVMeSensor(iter); + readAndProcessNVMeSensor(); return; } @@ -326,7 +325,7 @@ void NVMeBasicContext::readAndProcessNVMeSensor( response->prepare(len); return len; }, - [self{shared_from_this()}, iter, sensor, response]( + [self{shared_from_this()}, sensor, response]( const boost::system::error_code& ec, std::size_t length) mutable { if (ec) { @@ -350,30 +349,30 @@ void NVMeBasicContext::readAndProcessNVMeSensor( self->processResponse(sensor, data.data(), data.size()); /* Enqueue processing of the next sensor */ - self->readAndProcessNVMeSensor(iter); + self->readAndProcessNVMeSensor(); }); } void NVMeBasicContext::pollNVMeDevices() { - auto scan = sensors.begin(); + pollCursor = sensors.begin(); scanTimer.expires_from_now(boost::posix_time::seconds(1)); - scanTimer.async_wait([self{shared_from_this()}, - scan](const boost::system::error_code errorCode) { - if (errorCode == boost::asio::error::operation_aborted) - { - return; - } + scanTimer.async_wait( + [self{shared_from_this()}](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(scan); - }); + self->readAndProcessNVMeSensor(); + }); } static double getTemperatureReading(int8_t reading)