summaryrefslogtreecommitdiffstats
path: root/src/Event.cpp
blob: 1a0816fcf3fe2dffacdac12f8579598d8f82a8fd (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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include "Event.hpp"
#include <easylogging++.h>

std::queue<Event> EventAgregator::eventsToHandle;
std::mutex EventAgregator::queueMutex;
bool EventAgregator::isStarted = false;
std::vector<EventListener *> EventAgregator::listeners;
std::mutex EventAgregator::listenersMutex;

EventListener::EventListener() {
	EventAgregator::RegisterListener(*this);
}

EventListener::~EventListener() {
	EventAgregator::UnregisterListener(*this);
}

void EventListener::PushEvent(Event event) {
	eventsMutex.lock();
	handlersMutex.lock();
	if (handlers[event.type]) {
		events.push(event);
	}
	handlersMutex.unlock();
	eventsMutex.unlock();
}

void EventListener::DirectCall(Event event)
{
    handlersMutex.lock();
    if (handlers[event.type])
        handlers[event.type](event.data);
    handlersMutex.unlock();
}

bool EventListener::IsEventsQueueIsNotEmpty() {
	eventsMutex.lock();
	bool value = !events.empty();
	eventsMutex.unlock();
	return value;
}


void EventListener::RegisterHandler(EventType type, EventListener::HandlerFunc handler) {
	handlersMutex.lock();
	handlers[type] = handler;
	handlersMutex.unlock();
}

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


void EventAgregator::RegisterListener(EventListener &listener) {
	listenersMutex.lock();
	//LOG(WARNING) << "Registered handler " << &listener;
	listeners.push_back(&listener);
	listenersMutex.unlock();
}

void EventAgregator::UnregisterListener(EventListener &listener) {
	listenersMutex.lock();
	//LOG(WARNING) << "Unregistered handler " << &listener;
	listeners.erase(std::find(listeners.begin(), listeners.end(), &listener));
	listenersMutex.unlock();
}

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

void EventAgregator::DirectEventCall(EventType type, EventData data)
{
    Event event {type, data};
    listenersMutex.lock();
    for (auto &listener : listeners) {
        listenersMutex.unlock();
        listener->DirectCall(event);
        listenersMutex.lock();
    }
    listenersMutex.unlock();
}

void EventAgregator::EventHandlingLoop() {
    LoopExecutionTimeController timer(std::chrono::milliseconds(5));
	while (true) {
		queueMutex.lock();
		if (!eventsToHandle.empty()) {
			auto queue = std::move(eventsToHandle);            
			queueMutex.unlock();

			while (!queue.empty()) {
				auto event = queue.front();
				listenersMutex.lock();
				for (auto &listener : listeners) {
					listener->PushEvent(event);
				}
				listenersMutex.unlock();
				queue.pop();
			}

			queueMutex.lock();
		}
		queueMutex.unlock();
        timer.Update();
	}
}