add event system and use it to propagate to print traces

This commit is contained in:
2026-06-05 17:18:17 +02:00
parent abc261c03a
commit 9677133c54
14 changed files with 369 additions and 10 deletions

View File

@@ -0,0 +1,23 @@
add_subdirectory(event)
SET(HDRS
${HDRS}
${CMAKE_CURRENT_SOURCE_DIR}/Event.h
${CMAKE_CURRENT_SOURCE_DIR}/EventHandler.h
${CMAKE_CURRENT_SOURCE_DIR}/EventHandlerBase.h
${CMAKE_CURRENT_SOURCE_DIR}/EventManager.h
PARENT_SCOPE
)
SET(SRCS
${SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/EventHandlerBase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/EventManager.cpp
PARENT_SCOPE
)
SET(LIB_INCLUDE_PATH
${LIB_INCLUDE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}
PARENT_SCOPE
)

View File

@@ -0,0 +1,10 @@
#ifndef EVENT_H
#define EVENT_H
class Event
{
public:
virtual ~Event() = default;
};
#endif // EVENT_H

View File

@@ -0,0 +1,80 @@
#ifndef EVENT_HANDLER_H
#define EVENT_HANDLER_H
#include <memory>
#include "EventHandlerBase.h"
#include "EventManager.h"
template <typename T>
class EventHandler: public EventHandlerBase
{
public:
void registerForEvent()
{
EventManager::getInstance()->registerEventHandler(this);
}
void unregisterForEvent()
{
EventManager::getInstance()->unregisterEventHandler(this);
}
void handleBaseEvent(std::shared_ptr<const Event> event) override
{
std::shared_ptr<const T> specificEvent = std::dynamic_pointer_cast<const T>(event);
if (specificEvent)
{
handleEvent(specificEvent);
}
}
private:
virtual void handleEvent(std::shared_ptr<const T> event) = 0;
};
template <typename... Ts> class CombinedEventHandlerHelper
{
protected:
void registerForEventsHelper() {}
void unregisterForEventsHelper() {}
};
template <typename T, typename... Ts>
class CombinedEventHandlerHelper<T, Ts...>
: public EventHandler<T>
, public CombinedEventHandlerHelper<Ts...>
{
protected:
void registerForEventsHelper()
{
EventHandler<T>::registerForEvent();
CombinedEventHandlerHelper<Ts...>::registerForEventsHelper();
}
void unregisterForEventsHelper()
{
EventHandler<T>::unregisterForEvent();
CombinedEventHandlerHelper<Ts...>::unregisterForEventsHelper();
}
};
template <typename... Ts>
class CombinedEventHandler: public CombinedEventHandlerHelper<Ts...>
{
protected:
void registerForEvents()
{
CombinedEventHandlerHelper<Ts...>::registerForEventsHelper();
}
void unregisterForEvents()
{
CombinedEventHandlerHelper<Ts...>::unregisterForEventsHelper();
}
};
#endif // EVENT_HANDLER_H

View File

@@ -0,0 +1,7 @@
#include "EventHandlerBase.h"
unsigned int EventHandlerBase::s_nextId = 0;
EventHandlerBase::EventHandlerBase(): m_id(s_nextId++)
{
}

View File

@@ -0,0 +1,25 @@
#ifndef EVENT_HANDLER_BASE_H
#define EVENT_HANDLER_BASE_H
#include <memory>
class Event;
class EventManager;
class EventHandlerBase
{
private:
static unsigned int s_nextId;
public:
EventHandlerBase();
virtual ~EventHandlerBase() = default;
virtual void handleBaseEvent(std::shared_ptr<const Event> event) = 0;
private:
const unsigned int m_id;
friend EventManager;
};
#endif // EVENT_HANDLER_BASE_H

View File

@@ -0,0 +1,123 @@
#include "EventManager.h"
#include <set>
#include "EventHandlerBase.h"
std::shared_ptr<EventManager> EventManager::getInstance()
{
if (!s_instance)
{
s_instance = std::shared_ptr<EventManager>(new EventManager());
}
return s_instance;
}
void EventManager::destroyInstance()
{
if (s_instance)
{
s_instance.reset();
}
}
std::shared_ptr<EventManager> EventManager::s_instance = std::shared_ptr<EventManager>();
void EventManager::registerEventHandler(EventHandlerBase *eventHandler)
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
m_eventHandlers[eventHandler->m_id] = eventHandler;
}
void EventManager::unregisterEventHandler(EventHandlerBase *eventHandler)
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
m_eventHandlers.erase(eventHandler->m_id);
}
void EventManager::sendEventImmediately(std::shared_ptr<Event> event)
{
if (event)
{
std::set<unsigned int> eventHandlerIds;
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
for (auto it : m_eventHandlers)
{
eventHandlerIds.insert(it.first);
}
}
for (unsigned int id : eventHandlerIds)
{
// this is necessary to allow HandleBaseEvent() to remove event handlers without causing a crash
EventHandlerBase *eventHandler = nullptr;
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
auto it = m_eventHandlers.find(id);
if (it != m_eventHandlers.end())
{
eventHandler = it->second;
}
}
if (eventHandler)
{
eventHandler->handleBaseEvent(event);
}
}
}
}
void EventManager::addEvent(std::shared_ptr<Event> event)
{
if (event)
{
std::scoped_lock<std::mutex> lock(m_eventsMutex);
m_events.push_back(event);
}
}
void EventManager::processEvents()
{
std::vector<std::shared_ptr<Event>> events;
{
std::scoped_lock<std::mutex> lock(m_eventsMutex);
events = m_events;
m_events.clear();
}
std::set<unsigned int> eventHandlerIds;
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
for (auto it : m_eventHandlers)
{
eventHandlerIds.insert(it.first);
}
}
for (std::shared_ptr<Event> event : events)
{
for (unsigned int id : eventHandlerIds)
{
// this is necessary to allow HandleBaseEvent() to remove event handlers without causing a crash
EventHandlerBase *eventHandler = nullptr;
{
std::scoped_lock<std::mutex> lock(m_eventHandlersMutex);
auto it = m_eventHandlers.find(id);
if (it != m_eventHandlers.end())
{
eventHandler = it->second;
}
}
if (eventHandler)
{
eventHandler->handleBaseEvent(event);
}
}
}
}
bool EventManager::hasEvents() const
{
return !m_events.empty();
}

View File

@@ -0,0 +1,43 @@
#ifndef EVENT_MANAGER_H
#define EVENT_MANAGER_H
#include <map>
#include <memory>
#include <mutex>
#include <vector>
#include "Event.h"
class EventHandlerBase;
class EventManager
{
public:
static std::shared_ptr<EventManager> getInstance();
static void destroyInstance();
private:
static std::shared_ptr<EventManager> s_instance;
public:
EventManager(EventManager const &) = delete;
void operator=(EventManager const &) = delete;
void registerEventHandler(EventHandlerBase *eventHandler);
void unregisterEventHandler(EventHandlerBase *eventHandler);
void sendEventImmediately(std::shared_ptr<Event> event);
void addEvent(std::shared_ptr<Event> event);
void processEvents();
bool hasEvents() const;
private:
EventManager() = default;
std::map<unsigned int, EventHandlerBase *> m_eventHandlers;
std::vector<std::shared_ptr<Event>> m_events;
std::mutex m_eventHandlersMutex;
std::mutex m_eventsMutex;
};
#endif // EVENT_MANAGER_H

View File

@@ -0,0 +1,17 @@
SET(HDRS
${HDRS}
${CMAKE_CURRENT_SOURCE_DIR}/TracePrintRequestedEvent.h
PARENT_SCOPE
)
SET(SRCS
${SRCS}
${CMAKE_CURRENT_SOURCE_DIR}/TracePrintRequestedEvent.cpp
PARENT_SCOPE
)
set(LIB_INCLUDE_PATH
${LIB_INCLUDE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}
PARENT_SCOPE
)

View File

@@ -0,0 +1 @@
#include "TracePrintRequestedEvent.h"

View File

@@ -0,0 +1,10 @@
#ifndef TRACE_PRINT_REQUESTED_EVENT_H
#define TRACE_PRINT_REQUESTED_EVENT_H
#include "Event.h"
class TracePrintRequestedEvent : public Event
{
};
#endif // TRACE_PRINT_REQUESTED_EVENT_H