logic: fixed crash when calling message listeners that already have been destroyed

* prevented lambda created by MessageQueue::sendMessageAsTask to call functions on message listeners that already have been destroyed.
This commit is contained in:
malte_langkabel
2015-12-03 13:54:47 +01:00
parent 23909058c8
commit 151b4d8620
5 changed files with 40 additions and 2 deletions
+1
View File
@@ -283,6 +283,7 @@ add_files(
utility/messaging/Message.h
utility/messaging/MessageBase.h
utility/messaging/MessageListener.h
utility/messaging/MessageListenerBase.cpp
utility/messaging/MessageListenerBase.h
utility/messaging/MessageQueue.cpp
utility/messaging/MessageQueue.h
@@ -0,0 +1,3 @@
#include "utility/messaging/MessageListenerBase.h"
uint MessageListenerBase::s_nextId = 0;
@@ -5,11 +5,13 @@
#include "utility/messaging/MessageBase.h"
#include "utility/messaging/MessageQueue.h"
#include "utility/types.h"
class MessageListenerBase
{
public:
MessageListenerBase()
: m_id(s_nextId++)
{
MessageQueue::getInstance()->registerListener(this);
}
@@ -19,9 +21,19 @@ public:
MessageQueue::getInstance()->unregisterListener(this);
}
uint getId() const
{
return m_id;
}
virtual std::string getType() const = 0;
virtual void handleMessageBase(MessageBase*) = 0;
private:
static uint s_nextId;
uint m_id;
};
#endif // MESSAGE_LISTENER_BASE_H
+20 -2
View File
@@ -53,6 +53,19 @@ void MessageQueue::unregisterListener(MessageListenerBase* listener)
LOG_ERROR("Listener was not found");
}
MessageListenerBase* MessageQueue::getListenerById(const uint id) const
{
std::lock_guard<std::mutex> lock(m_listenersMutex);
for (size_t i = 0; i < m_listeners.size(); i++)
{
if (m_listeners[i]->getId() == id)
{
return m_listeners[i];
}
}
return nullptr;
}
void MessageQueue::pushMessage(std::shared_ptr<MessageBase> message)
{
std::lock_guard<std::mutex> lock(m_backMessageBufferMutex);
@@ -240,10 +253,15 @@ void MessageQueue::sendMessageAsTask(std::shared_ptr<MessageBase> message, bool
if (listener->getType() == message->getType())
{
uint listenerId = listener->getId();
taskGroup->addTask(std::make_shared<LambdaTask>(
[listener, message]()
[listenerId, message]()
{
listener->handleMessageBase(message.get());
MessageListenerBase* listener = MessageQueue::getInstance()->getListenerById(listenerId);
if (listener)
{
listener->handleMessageBase(message.get());
}
}
));
}
+4
View File
@@ -5,6 +5,8 @@
#include <mutex>
#include <queue>
#include "utility/types.h"
class MessageBase;
class MessageListenerBase;
@@ -16,6 +18,8 @@ public:
void registerListener(MessageListenerBase* listener);
void unregisterListener(MessageListenerBase* listener);
MessageListenerBase* getListenerById(const uint id) const;
void pushMessage(std::shared_ptr<MessageBase> message);
void processMessage(std::shared_ptr<MessageBase> message, bool asNextTask);