From 46681e0bd33a0219ae6af86ed5e4264e591c4354 Mon Sep 17 00:00:00 2001 From: Tobias Markus Date: Tue, 25 Sep 2018 14:51:41 +0200 Subject: [PATCH] event: Refactoring Most notably, it is now possible to post multiple events at once (locking the mutex only once). --- src/events/EventSystem.cpp | 24 +++++++++++++++------ src/events/EventSystem.h | 38 +++++++++++++++++++++++++-------- src/gamestate/GameNetworker.cpp | 28 +++++++++++++++++------- src/gamestate/GameNetworker.h | 2 +- 4 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/events/EventSystem.cpp b/src/events/EventSystem.cpp index 15d8d969..b690646f 100644 --- a/src/events/EventSystem.cpp +++ b/src/events/EventSystem.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include @@ -28,18 +29,29 @@ void EventSystem::removeListener(ListenerFunction* listener) } } -void EventSystem::postEvent(std::shared_ptr _event, double offset) +void EventSystem::postEvent(const std::shared_ptr event) { + postEvent(TimedEvent{ event }); +} + +void EventSystem::postEvent(const TimedEvent& event) +{ + std::lock_guard queueGuard{ queueLock }; + eventQueue.emplace(event); +} + +void EventSystem::postEvents(const std::vector& events) { - std::lock_guard queueGuard(queueLock); - eventQueue.emplace(_event, glfwGetTime() + offset); + std::lock_guard queueGuard{ queueLock }; + std::for_each(events.cbegin(), events.cend(), [&](const auto& event) { eventQueue.push(event); }); } void EventSystem::update(double deltaTime, double timeStamp) { - std::lock_guard queueGuard(queueLock); - while (!eventQueue.empty() && eventQueue.top().is_due()) + std::lock_guard queueGuard{ queueLock }; + const double now = glfwGetTime(); + while (!eventQueue.empty() && eventQueue.top().is_due_at(now)) { - processEvent(eventQueue.top().m_event); + processEvent(eventQueue.top().get()); eventQueue.pop(); } } diff --git a/src/events/EventSystem.h b/src/events/EventSystem.h index 55ccf560..a2abeea5 100644 --- a/src/events/EventSystem.h +++ b/src/events/EventSystem.h @@ -16,23 +16,39 @@ #include -struct TimedEvent { +class TimedEvent { +protected: double m_due; std::shared_ptr m_event; + bool m_immediate; - TimedEvent(std::shared_ptr event, double due) - : m_event{event} - , m_due{ due } +public: + TimedEvent(const std::shared_ptr& event) + : m_event{ event } + , m_due{ 0.0 } + , m_immediate{ true } {} + TimedEvent(const std::shared_ptr& event, const double offset) + : m_event{ event } + , m_due{ glfwGetTime() + offset } + , m_immediate{ false } + {} + TimedEvent() = delete; - bool is_due() const { - return glfwGetTime() >= m_due; + inline bool is_due_at(const double time) const noexcept { + return m_immediate || time >= m_due; + } + bool is_due() const noexcept { + return is_due_at(glfwGetTime()); + } + std::shared_ptr get() const noexcept { + return m_event; } - bool operator<(const TimedEvent& rhs) const { + bool operator<(const TimedEvent& rhs) const noexcept { return m_due < rhs.m_due; } - bool operator>(const TimedEvent& rhs) const { + bool operator>(const TimedEvent& rhs) const noexcept { return m_due > rhs.m_due; } }; @@ -49,7 +65,11 @@ class EventSystem void registerListener(ListenerFunction* listener); void removeListener(ListenerFunction* listener); - void postEvent(std::shared_ptr _event, double offset = 0.0); + + void postEvent(const std::shared_ptr event); + void postEvent(const TimedEvent& event); + void postEvents(const std::vector& events); + void processEvent(std::shared_ptr _event); protected: std::vector listeners; diff --git a/src/gamestate/GameNetworker.cpp b/src/gamestate/GameNetworker.cpp index 9764fb87..fe8b21b6 100644 --- a/src/gamestate/GameNetworker.cpp +++ b/src/gamestate/GameNetworker.cpp @@ -200,26 +200,38 @@ static const double offset(const CommandType& type) { return 0.0; } -void GameNetworker::processCommands(nlohmann::json& jsonCommands) +std::vector> GameNetworker::processCommands(const nlohmann::json& jsonCommands) { + std::vector> commands; for (const nlohmann::json& jsonCommand : jsonCommands) { std::shared_ptr command = parseCommand(jsonCommand); - if (command) { - eventSystem.postEvent(std::make_shared(command), offset(command->type())); + if (command) { + commands.emplace_back(command); } } + return commands; } void GameNetworker::onStateReceive(sio::event _event) { const string jsonMessage = _event.get_message()->get_string(); - nlohmann::json jsonState = nlohmann::json::parse(jsonMessage); - auto state = parseGamestate(jsonState); - - eventSystem.postEvent(std::make_shared(state)); + const nlohmann::json jsonState = nlohmann::json::parse(jsonMessage); + const auto state = parseGamestate(jsonState); + const auto jsonCommands = jsonState["commands"]; + + + std::vector events; + events.reserve(jsonCommands.size() + 1); + events.emplace_back(std::make_shared(state)); + for (const nlohmann::json& jsonCommand : jsonCommands) + { + if (std::shared_ptr command = parseCommand(jsonCommand)) { + events.emplace_back(std::make_shared(command), offset(command->type())); + } + } - processCommands(jsonState["commands"]); + eventSystem.postEvents(events); } void GameNetworker::onInitStateReceive(sio::event _event) diff --git a/src/gamestate/GameNetworker.h b/src/gamestate/GameNetworker.h index 46a48048..57bb0074 100644 --- a/src/gamestate/GameNetworker.h +++ b/src/gamestate/GameNetworker.h @@ -42,5 +42,5 @@ class GameNetworker : public Networker std::shared_ptr parseGamestate(nlohmann::json state); Configuration parseConfiguration(std::string jsonString); std::shared_ptr parseCommand(const nlohmann::json& jsonCommand); - void processCommands(nlohmann::json& commands); + std::vector> processCommands(const nlohmann::json& commands); }; \ No newline at end of file