Skip to content

Commit

Permalink
event: Refactoring
Browse files Browse the repository at this point in the history
Most notably, it is now possible to post multiple events at once (locking the mutex only once).
  • Loading branch information
hesiod committed Sep 25, 2018
1 parent b0c0f2f commit 46681e0
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
24 changes: 18 additions & 6 deletions src/events/EventSystem.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <algorithm>
#include <mutex>
#include <cassert>
#include <functional>

#include <events/EventSystem.h>

Expand Down Expand Up @@ -28,18 +29,29 @@ void EventSystem::removeListener(ListenerFunction* listener)
}
}

void EventSystem::postEvent(std::shared_ptr<Event> _event, double offset)
void EventSystem::postEvent(const std::shared_ptr<Event> event) {
postEvent(TimedEvent{ event });
}

void EventSystem::postEvent(const TimedEvent& event)
{
std::lock_guard<std::mutex> queueGuard{ queueLock };
eventQueue.emplace(event);
}

void EventSystem::postEvents(const std::vector<TimedEvent>& events)
{
std::lock_guard<std::mutex> queueGuard(queueLock);
eventQueue.emplace(_event, glfwGetTime() + offset);
std::lock_guard<std::mutex> 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<std::mutex> queueGuard(queueLock);
while (!eventQueue.empty() && eventQueue.top().is_due())
std::lock_guard<std::mutex> 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();
}
}
Expand Down
38 changes: 29 additions & 9 deletions src/events/EventSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,39 @@
#include <events/Event.h>


struct TimedEvent {
class TimedEvent {
protected:
double m_due;
std::shared_ptr<Event> m_event;
bool m_immediate;

TimedEvent(std::shared_ptr<Event> event, double due)
: m_event{event}
, m_due{ due }
public:
TimedEvent(const std::shared_ptr<Event>& event)
: m_event{ event }
, m_due{ 0.0 }
, m_immediate{ true }
{}
TimedEvent(const std::shared_ptr<Event>& 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<Event> 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;
}
};
Expand All @@ -49,7 +65,11 @@ class EventSystem

void registerListener(ListenerFunction* listener);
void removeListener(ListenerFunction* listener);
void postEvent(std::shared_ptr<Event> _event, double offset = 0.0);

void postEvent(const std::shared_ptr<Event> event);
void postEvent(const TimedEvent& event);
void postEvents(const std::vector<TimedEvent>& events);

void processEvent(std::shared_ptr<Event> _event);
protected:
std::vector<ListenerFunction*> listeners;
Expand Down
28 changes: 20 additions & 8 deletions src/gamestate/GameNetworker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,26 +200,38 @@ static const double offset(const CommandType& type) {
return 0.0;
}

void GameNetworker::processCommands(nlohmann::json& jsonCommands)
std::vector<std::shared_ptr<Command>> GameNetworker::processCommands(const nlohmann::json& jsonCommands)
{
std::vector<std::shared_ptr<Command>> commands;
for (const nlohmann::json& jsonCommand : jsonCommands)
{
std::shared_ptr<Command> command = parseCommand(jsonCommand);
if (command) {
eventSystem.postEvent(std::make_shared<CommandEvent>(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<StateEvent>(state));
const nlohmann::json jsonState = nlohmann::json::parse(jsonMessage);
const auto state = parseGamestate(jsonState);
const auto jsonCommands = jsonState["commands"];


std::vector<TimedEvent> events;
events.reserve(jsonCommands.size() + 1);
events.emplace_back(std::make_shared<StateEvent>(state));
for (const nlohmann::json& jsonCommand : jsonCommands)
{
if (std::shared_ptr<Command> command = parseCommand(jsonCommand)) {
events.emplace_back(std::make_shared<CommandEvent>(command), offset(command->type()));
}
}

processCommands(jsonState["commands"]);
eventSystem.postEvents(events);
}

void GameNetworker::onInitStateReceive(sio::event _event)
Expand Down
2 changes: 1 addition & 1 deletion src/gamestate/GameNetworker.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@ class GameNetworker : public Networker
std::shared_ptr<Gamestate> parseGamestate(nlohmann::json state);
Configuration parseConfiguration(std::string jsonString);
std::shared_ptr<class Command> parseCommand(const nlohmann::json& jsonCommand);
void processCommands(nlohmann::json& commands);
std::vector<std::shared_ptr<Command>> processCommands(const nlohmann::json& commands);
};

0 comments on commit 46681e0

Please sign in to comment.