summaryrefslogtreecommitdiffstats
path: root/src/core/Event.hpp
blob: cfa990a5edec9e18c088a8e494d16340be7d3839 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#pragma once

#include <queue>
#include <map>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <variant>
#include <functional>

#include <Vector.hpp>

enum class EventType {
	Echo,
	ChunkChanged,
};

struct EchoData {
	std::chrono::time_point<std::chrono::high_resolution_clock> time;
};

struct ChunkChangedData {
	Vector chunkPosition;
};

using EventData = std::variant<EchoData, ChunkChangedData>;

struct Event {
	EventType type;
	EventData data;
};

class EventListener {
	friend class EventAgregator;

	using HandlerFunc = std::function<void(EventData)>;

	std::map<EventType, HandlerFunc> handlers; //TODO: There must be more elegant solution than std::variant of all data

	std::mutex eventsMutex;

	std::queue<Event> events;

	void PushEvent(Event event);

public:
	EventListener();
	~EventListener();
	bool IsEventsQueueIsNotEmpty();

	void RegisterHandler(EventType type, HandlerFunc handler) {
		handlers[type] = handler;
	}

	void HandleEvent() {
		eventsMutex.lock();
		if (events.empty()) {
			eventsMutex.unlock();
			return;
		}
		Event event = events.front();
		events.pop();
		eventsMutex.unlock();
		auto function = handlers[event.type];
		function(event.data);
	}
};

class EventAgregator {
	friend EventListener;

	EventAgregator() = default;
	static std::queue<Event> eventsToHandle;
	static std::mutex queueMutex;
	static bool isStarted;
	static std::vector<EventListener *> listeners;
	static std::mutex listenersMutex;

	static void EventHandlingLoop();

	static void RegisterListener(EventListener &listener);
	static void UnregisterListener(EventListener &listener);

public:
	static void PushEvent(EventType type, EventData data) {
		if (!isStarted) {
			isStarted = true;
			std::thread(&EventAgregator::EventHandlingLoop).detach();
		}
		Event event;
		event.type = type;
		event.data = data;
		eventsToHandle.push(event);
	}
};