diff --git a/CHANGELOG.md b/CHANGELOG.md index 525ec4d..f298734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Application singleton now uses protected constructor and logic_error check +### Fixed + +- Fix window ownership and event bus safety + ## [0.6.0] - 2026-02-15 - Change headers parent folder to Kappa diff --git a/include/Kappa/Application.h b/include/Kappa/Application.h index 736d360..b88a368 100644 --- a/include/Kappa/Application.h +++ b/include/Kappa/Application.h @@ -134,7 +134,7 @@ namespace Kappa private: ApplicationSpecification specification; ///< Application configuration std::vector> layerStack; ///< Stack of application layers - std::shared_ptr window; ///< Main application window + std::unique_ptr window; ///< Main application window bool isRunning = false; ///< Flag indicating if the application is running EventBus eventBus; ///< Event bus for inter-layer communication }; diff --git a/include/Kappa/EventBus.h b/include/Kappa/EventBus.h index c411337..8156848 100644 --- a/include/Kappa/EventBus.h +++ b/include/Kappa/EventBus.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -25,8 +26,14 @@ namespace Kappa requires std::is_base_of_v void Subscribe(std::function callback) { + std::lock_guard lock(subscribersMutex); const auto typeIndex = std::type_index(typeid(TEvent)); - auto wrapper = [callback](const Event &event) { callback(static_cast(event)); }; + auto wrapper = [callback](const Event &event) { + if (const auto *specEvent = dynamic_cast(&event)) + { + callback(*specEvent); + } + }; subscribers[typeIndex].push_back(wrapper); } @@ -39,14 +46,20 @@ namespace Kappa requires std::is_base_of_v void Publish(const TEvent &event) { - const auto typeIndex = std::type_index(typeid(TEvent)); - if (const auto it = subscribers.find(typeIndex); it != subscribers.end()) + std::vector handlers; { - for (const auto &callback : it->second) + std::lock_guard lock(subscribersMutex); + const auto typeIndex = std::type_index(typeid(TEvent)); + if (const auto it = subscribers.find(typeIndex); it != subscribers.end()) { - callback(event); + handlers = it->second; } } + + for (const auto &callback : handlers) + { + callback(event); + } } /** @@ -54,11 +67,13 @@ namespace Kappa */ void Clear() { + std::lock_guard lock(subscribersMutex); subscribers.clear(); } private: using EventCallback = std::function; std::unordered_map> subscribers; + mutable std::mutex subscribersMutex; }; } // namespace Kappa diff --git a/src/Application.cpp b/src/Application.cpp index 2037cce..f13c1c0 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -34,7 +34,7 @@ namespace Kappa specification.windowSpecification.title = specification.name; } - window = std::make_shared(specification.windowSpecification); + window = std::make_unique(specification.windowSpecification); window->Create(); }