From ef16e60025a86d89b699e7cd2048fd54f888fd2f Mon Sep 17 00:00:00 2001 From: EricLiu2000 Date: Wed, 7 Aug 2019 13:12:16 -0400 Subject: [PATCH] Added more mutexes in eventmanager, fixed exiting destruction bug --- api/icsneocpp/eventmanager.cpp | 26 +++++++++++++++++++------- device/device.cpp | 1 + include/icsneo/api/eventmanager.h | 25 +++++++++++++++++++++---- include/icsneo/device/device.h | 6 +----- test/eventmanagertest.cpp | 2 +- 5 files changed, 43 insertions(+), 17 deletions(-) diff --git a/api/icsneocpp/eventmanager.cpp b/api/icsneocpp/eventmanager.cpp index 481c8a3..1fd3c32 100644 --- a/api/icsneocpp/eventmanager.cpp +++ b/api/icsneocpp/eventmanager.cpp @@ -3,20 +3,32 @@ using namespace icsneo; -static std::unique_ptr singleton; - EventManager& EventManager::GetInstance() { - if(!singleton) - singleton = std::unique_ptr(new EventManager()); - return *singleton.get(); + static EventManager inst; + return inst; } void EventManager::ResetInstance() { - singleton = std::unique_ptr(new EventManager()); + std::lock_guard eventsLock(eventsMutex); + std::lock_guard errorsLock(errorsMutex); + std::lock_guard downgradedThreadsLock(downgradedThreadsMutex); + std::lock_guard callbacksLock(callbacksMutex); + + std::lock_guard callbackIDLock(callbackIDMutex); + std::lock_guard eventLimitLock(eventLimitMutex); + + events.clear(); + lastUserErrors.clear(); + downgradedThreads.clear(); + callbacks.clear(); + + callbackID = 0; + eventLimit = 10000; } int EventManager::addEventCallback(const EventCallback &cb) { - std::lock_guard lk(callbacksMutex); + std::lock_guard callbacksLock(callbacksMutex); + std::lock_guard callbackIDLock(callbackIDMutex); callbacks.insert({callbackID, cb}); return callbackID++; } diff --git a/device/device.cpp b/device/device.cpp index 610eab0..5155846 100644 --- a/device/device.cpp +++ b/device/device.cpp @@ -1,5 +1,6 @@ #include "icsneo/device/device.h" #include "icsneo/communication/message/callback/messagecallback.h" +#include "icsneo/api/eventmanager.h" #include "icsneo/communication/command.h" #include #include diff --git a/include/icsneo/api/eventmanager.h b/include/icsneo/api/eventmanager.h index 1cce3aa..55e86ac 100644 --- a/include/icsneo/api/eventmanager.h +++ b/include/icsneo/api/eventmanager.h @@ -17,13 +17,19 @@ typedef std::function device_eventhan class EventManager { public: + ~EventManager() { + destructing = true; + } + static EventManager& GetInstance(); - static void ResetInstance(); + void ResetInstance(); // If this thread is not in the map, add it to be ignored // If it is, set it to be ignored void downgradeErrorsOnCurrentThread() { + if(destructing) + return; std::lock_guard lk(downgradedThreadsMutex); auto i = downgradedThreads.find(std::this_thread::get_id()); if(i != downgradedThreads.end()) { @@ -35,6 +41,8 @@ public: // If this thread exists in the map, turn off downgrading void cancelErrorDowngradingOnCurrentThread() { + if(destructing) + return; std::lock_guard lk(downgradedThreadsMutex); auto i = downgradedThreads.find(std::this_thread::get_id()); if(i != downgradedThreads.end()) { @@ -63,6 +71,8 @@ public: APIEvent getLastError(); void add(APIEvent event) { + if(destructing) + return; if(event.getSeverity() == APIEvent::Severity::Error) { // if the error was added on a thread that downgrades errors (non-user thread) std::lock_guard lk(downgradedThreadsMutex); @@ -93,7 +103,7 @@ public: void discard(EventFilter filter = EventFilter()); void setEventLimit(size_t newLimit) { - std::lock_guard lk(eventsMutex); + std::lock_guard eventLimitLock(eventLimitMutex); if(newLimit == eventLimit) return; @@ -104,17 +114,19 @@ public: } eventLimit = newLimit; + + std::lock_guard eventsLock(eventsMutex); if(enforceLimit()) add_internal_event(APIEvent(APIEvent::Type::TooManyEvents, APIEvent::Severity::EventWarning)); } size_t getEventLimit() const { - std::lock_guard lk(eventsMutex); + std::lock_guard lk(eventLimitMutex); return eventLimit; } private: - EventManager() : eventsMutex(), errorsMutex(), downgradedThreadsMutex(), callbacksMutex(), downgradedThreads(), callbacks(), events(), lastUserErrors(), eventLimit(10000) {} + EventManager() : eventsMutex(), errorsMutex(), downgradedThreadsMutex(), callbacksMutex(), callbackIDMutex(), eventLimitMutex(), downgradedThreads(), callbacks(), events(), lastUserErrors(), eventLimit(10000) {} EventManager(const EventManager &other); EventManager& operator=(const EventManager &other); @@ -124,12 +136,17 @@ private: mutable std::mutex downgradedThreadsMutex; mutable std::mutex callbacksMutex; + mutable std::mutex callbackIDMutex; + mutable std::mutex eventLimitMutex; + std::map downgradedThreads; std::map callbacks; int callbackID = 0; + bool destructing = false; + // Stores all events std::list events; std::map lastUserErrors; diff --git a/include/icsneo/device/device.h b/include/icsneo/device/device.h index 6567f06..0591197 100644 --- a/include/icsneo/device/device.h +++ b/include/icsneo/device/device.h @@ -22,7 +22,6 @@ namespace icsneo { class Device { public: virtual ~Device() { - destructing = true; if(isMessagePollingEnabled()) disableMessagePolling(); close(); @@ -121,8 +120,7 @@ protected: virtual device_eventhandler_t makeEventHandler() { return [this](APIEvent::Type type, APIEvent::Severity severity) { - if(!destructing) - EventManager::GetInstance().add(type, severity, this); + EventManager::GetInstance().add(type, severity, this); }; } @@ -178,8 +176,6 @@ private: size_t pollingMessageLimit = 20000; moodycamel::BlockingConcurrentQueue> pollingContainer; void enforcePollingMessageLimit(); - - bool destructing = false; }; } diff --git a/test/eventmanagertest.cpp b/test/eventmanagertest.cpp index 2de8237..453548c 100644 --- a/test/eventmanagertest.cpp +++ b/test/eventmanagertest.cpp @@ -11,7 +11,7 @@ class EventManagerTest : public ::testing::Test { protected: // Start with a clean instance of eventmanager for every test void SetUp() override { - EventManager::ResetInstance(); + EventManager::GetInstance().ResetInstance(); } };