Device: Allow the suppression of disconnects from extensions

pull/35/head
Paul Hollinsky 2021-04-23 20:04:02 -04:00
parent 6c1cbc9db8
commit 4cd7bafca7
4 changed files with 68 additions and 2 deletions

View File

@ -240,13 +240,13 @@ bool Device::open() {
while(!stopHeartbeatThread) {
// Wait for 110ms for a possible heartbeat
std::this_thread::sleep_for(std::chrono::milliseconds(110));
if(!receivedMessage) {
if(!receivedMessage && !heartbeatSuppressed()) {
// No heartbeat received, request a status
com->sendCommand(Command::RequestStatusUpdate);
// The response should come back quickly if the com is quiet
std::this_thread::sleep_for(std::chrono::milliseconds(10));
// Check if we got a message, and if not, if settings are being applied
if(!receivedMessage && !settings->applyingSettings) {
if(!receivedMessage && !heartbeatSuppressed()) {
if(!stopHeartbeatThread && !isDisconnected())
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
break;
@ -630,6 +630,11 @@ optional<double> Device::getAnalogIO(IO type, size_t number /* = 1 */) {
return nullopt;
}
Lifetime Device::suppressDisconnects() {
heartbeatSuppressedByUser++;
return Lifetime([this] { heartbeatSuppressedByUser--; });
}
void Device::addExtension(std::shared_ptr<DeviceExtension>&& extension) {
std::lock_guard<std::mutex> lk(extensionsLock);
extensions.push_back(extension);

View File

@ -0,0 +1,34 @@
#ifndef __ICSNEO_LIFETIME_H_
#define __ICSNEO_LIFETIME_H_
#include <functional>
namespace icsneo {
class Lifetime {
public:
Lifetime() = default;
Lifetime(std::function<void(void)> onDeath) : fnOnDeath(onDeath) {}
~Lifetime() {
if(fnOnDeath)
fnOnDeath();
}
// Disallow copies so the fnOnDeath only happens once
Lifetime(const Lifetime&) = delete;
Lifetime& operator=(const Lifetime&) = delete;
// Explicitly allow moves
Lifetime(Lifetime&& moved) { *this = std::move(moved); }
Lifetime& operator=(Lifetime&& rhs) {
fnOnDeath = std::move(rhs.fnOnDeath);
rhs.fnOnDeath = std::function<void(void)>();
return *this;
}
private:
std::function<void(void)> fnOnDeath;
};
}
#endif

View File

@ -9,6 +9,7 @@
#include <cstring>
#include <atomic>
#include "icsneo/api/eventmanager.h"
#include "icsneo/api/lifetime.h"
#include "icsneo/device/neodevice.h"
#include "icsneo/device/idevicesettings.h"
#include "icsneo/device/nullsettings.h"
@ -24,6 +25,7 @@
#include "icsneo/communication/message/flexray/control/flexraycontrolmessage.h"
#include "icsneo/third-party/concurrentqueue/concurrentqueue.h"
#include "icsneo/platform/optional.h"
#include "icsneo/platform/nodiscard.h"
namespace icsneo {
@ -155,6 +157,12 @@ public:
virtual std::vector<std::shared_ptr<FlexRay::Controller>> getFlexRayControllers() const { return {}; }
/**
* For use by extensions only.
*/
NODISCARD("If the Lifetime is not held, disconnects will be immediately unsuppressed")
Lifetime suppressDisconnects();
const device_eventhandler_t& getEventHandler() const { return report; }
std::shared_ptr<Communication> com;
@ -275,6 +283,10 @@ private:
std::vector<Network> supportedTXNetworks;
std::vector<Network> supportedRXNetworks;
// Use heartbeatSuppressed instead when reading
std::atomic<int> heartbeatSuppressedByUser{0};
bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); }
void handleNeoVIMessage(std::shared_ptr<CANMessage> message);
enum class LEDState : uint8_t {

View File

@ -0,0 +1,15 @@
#ifndef __ICSNEO_NODISCARD_H_
#define __ICSNEO_NODISCARD_H_
/**
* Allow the use of the nodiscard attribute where it is supported.
*/
#if __cplusplus > 201703L // C++20 and above
#define NODISCARD(str) [[nodiscard(str)]]
#elif __cplusplus > 201402L // C++17 and above
#define NODISCARD(str) [[nodiscard]]
#else
#define NODISCARD(str)
#endif
#endif