DiscordCoreAPI
A Discord bot library written in C++, with custom asynchronous coroutines.
Loading...
Searching...
No Matches
EventEntities.hpp
Go to the documentation of this file.
1/*
2 DiscordCoreAPI, A bot library for Discord, written in C++, and featuring explicit multithreading through the usage of custom, asynchronous C++ CoRoutines.
3
4 Copyright 2021, 2022, 2023 Chris M. (RealTimeChris)
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 USA
20*/
21/// EventEntities.hpp - Header for the "Event-related stuff".
22/// Dec 12, 2021
23/// https://discordcoreapi.com
24/// \file EventEntities.hpp
25
26#pragma once
27
29
30namespace DiscordCoreInternal {
31
32 /**
33 * \addtogroup discord_events
34 * @{
35 */
36
37 /// \brief Event-delegate token, representing an event.
38 struct DiscordCoreAPI_Dll EventDelegateToken {
39 template<typename RTy, typename... ArgTypes> friend class EventDelegate;
40
41 template<typename RTy, typename... ArgTypes> friend class Event;
42
43 template<typename RTy, typename... ArgTypes> friend class TriggerEventDelegate;
44
45 template<typename RTy, typename... ArgTypes> friend class TriggerEvent;
46
47 DiscordCoreAPI_Dll friend inline bool operator==(const EventDelegateToken& lhs, const EventDelegateToken& rhs);
48
49 DiscordCoreAPI_Dll friend inline bool operator<(const EventDelegateToken& lhs, const EventDelegateToken& rhs);
50
51 EventDelegateToken() noexcept = default;
52
53 protected:
54 std::string handlerId{};
55 std::string eventId{};
56 };
57
58 DiscordCoreAPI_Dll inline bool operator==(const EventDelegateToken& lhs, const EventDelegateToken& rhs) {
59 return lhs.eventId == rhs.eventId && lhs.handlerId == rhs.handlerId;
60 }
61
62 DiscordCoreAPI_Dll inline bool operator<(const EventDelegateToken& lhs, const EventDelegateToken& rhs) {
63 return stoll(lhs.handlerId) < stoll(rhs.handlerId);
64 }
65
66 /// \brief Event-delegate, for representing an event-function to be executed.
67 template<typename RTy, typename... ArgTypes> class EventDelegate {
68 public:
69 template<typename RTy02, typename... ArgTypes02> friend class Event;
70
71 EventDelegate<RTy, ArgTypes...>& operator=(EventDelegate<RTy, ArgTypes...>&& other) noexcept {
72 if (this != &other) {
73 function.swap(other.function);
74 other.function = std::function<RTy(ArgTypes...)>{};
75 }
76 return *this;
77 }
78
80 *this = std::move(other);
81 }
82
83 EventDelegate<RTy, ArgTypes...>& operator=(const EventDelegate<RTy, ArgTypes...>& other) = delete;
84
86
87 EventDelegate<RTy, ArgTypes...>& operator=(std::function<RTy(ArgTypes...)> functionNew) {
88 function = functionNew;
89 return *this;
90 }
91
92 /// \brief Constructor, taking a std::function<RTy(ArgTypes..)> as an argument.
93 EventDelegate(std::function<RTy(ArgTypes...)> functionNew) {
94 *this = functionNew;
95 }
96
97 EventDelegate<RTy, ArgTypes...>& operator=(RTy (*functionNew)(ArgTypes...)) {
98 function = functionNew;
99 return *this;
100 }
101
102 /// \brief Constructor, taking a pointer to a function of type RTy(*)(ArgTypes...) as an argument.
103 EventDelegate(RTy (*functionNew)(ArgTypes...)) {
104 *this = functionNew;
105 }
106
107 EventDelegate() noexcept = default;
108
109 protected:
110 std::function<RTy(ArgTypes...)> function{};
111 };
112
113 template<typename RTy, typename... ArgTypes> class Event {
114 public:
115 std::map<EventDelegateToken, EventDelegate<RTy, ArgTypes...>> functions{};
116
117 Event<RTy, ArgTypes...>& operator=(Event<RTy, ArgTypes...>&& other) noexcept {
118 if (this != &other) {
119 functions = std::move(other.functions);
120 other.functions = std::map<EventDelegateToken, EventDelegate<RTy, ArgTypes...>>{};
121 eventId = std::move(other.eventId);
122 other.eventId = std::string{};
123 }
124 return *this;
125 }
126
127 Event(Event<RTy, ArgTypes...>&& other) noexcept {
128 *this = std::move(other);
129 }
130
131 Event<RTy, ArgTypes...>& operator=(const Event<RTy, ArgTypes...>&) = delete;
132
133 Event(const Event<RTy, ArgTypes...>&) = delete;
134
135 Event() {
136 eventId = std::to_string(std::chrono::duration_cast<Microseconds>(HRClock::now().time_since_epoch()).count());
137 }
138
139 EventDelegateToken add(EventDelegate<RTy, ArgTypes...> eventDelegate) {
140 EventDelegateToken eventToken{};
141 eventToken.handlerId = std::to_string(std::chrono::duration_cast<Microseconds>(HRClock::now().time_since_epoch()).count());
142 eventToken.eventId = eventId;
143 functions[eventToken] = std::move(eventDelegate);
144 return eventToken;
145 }
146
147 void erase(EventDelegateToken eventToken) {
148 if (eventToken.eventId == eventId) {
149 if (functions.contains(eventToken)) {
150 functions.erase(eventToken);
151 }
152 }
153 }
154
155 std::vector<RTy> operator()(ArgTypes&... args) {
156 std::vector<RTy> vector{};
157 for (auto& [key, value]: functions) {
158 vector.emplace_back(value.function(args...));
159 }
160 return vector;
161 }
162
163 protected:
164 std::string eventId{};
165 };
166
167 /// \brief An event that gets fired depending on the result of a "trigger-function" return value.
168 template<typename RTy, typename... ArgTypes> class TriggerEventDelegate {
169 public:
170 template<typename RTy02, typename... ArgTypes02> friend class TriggerEvent;
171
172 TriggerEventDelegate<RTy, ArgTypes...>& operator=(TriggerEventDelegate<RTy, ArgTypes...>&& other) noexcept {
173 if (this != &other) {
174 function.swap(other.function);
175 other.function = std::function<RTy(ArgTypes...)>{};
176 testFunction.swap(other.testFunction);
177 other.testFunction = std::function<bool(ArgTypes...)>{};
178 }
179 return *this;
180 }
181
183 *this = std::move(other);
184 }
185
186 TriggerEventDelegate<RTy, ArgTypes...>& operator=(const TriggerEventDelegate<RTy, ArgTypes...>& other) = delete;
187
189
190 TriggerEventDelegate<RTy, ArgTypes...>& operator=(std::function<RTy(ArgTypes...)> functionNew) {
191 function = functionNew;
192 return *this;
193 }
194
195 /// \brief Constructor, taking a std::function<RTy(ArgTypes..)> as an argument.
196 TriggerEventDelegate(std::function<RTy(ArgTypes...)> functionNew) {
197 *this = functionNew;
198 }
199
200 TriggerEventDelegate<RTy, ArgTypes...>& operator=(RTy (*functionNew)(ArgTypes...)) {
201 function = functionNew;
202 return *this;
203 }
204
205 void setTestFunction(std::function<bool(ArgTypes...)> testFunctionNew) {
206 testFunction = testFunctionNew;
207 }
208
209 void setTestFunction(bool (*testFunctionNew)(ArgTypes...)) {
210 testFunction = testFunctionNew;
211 }
212
213 /// \brief Constructor, taking a pointer to a function of type RTy(*)(ArgTypes...) as an argument.
214 TriggerEventDelegate(RTy (*functionNew)(ArgTypes...)) {
215 *this = functionNew;
216 }
217
218 TriggerEventDelegate() noexcept = default;
219
220 protected:
221 std::function<bool(ArgTypes...)> testFunction{};
222 std::function<RTy(ArgTypes...)> function{};
223 };
224
225 /**@}*/
226
227 template<typename RTy, typename... ArgTypes> class TriggerEvent {
228 public:
229 std::map<EventDelegateToken, TriggerEventDelegate<RTy, ArgTypes...>> functions{};
230
231 TriggerEvent<RTy, ArgTypes...>& operator=(Event<RTy, ArgTypes...>&& other) noexcept {
232 if (this != &other) {
233 functions = std::move(other.functions);
234 other.functions = std::map<EventDelegateToken, TriggerEventDelegate<RTy, ArgTypes...>>{};
235 eventId = std::move(other.eventId);
236 other.eventId = std::string{};
237 }
238 return *this;
239 }
240
241 TriggerEvent(Event<RTy, ArgTypes...>&& other) noexcept {
242 *this = std::move(other);
243 }
244
245 TriggerEvent<RTy, ArgTypes...>& operator=(const Event<RTy, ArgTypes...>&) = delete;
246
247 TriggerEvent(const TriggerEvent<RTy, ArgTypes...>&) = delete;
248
249 TriggerEvent() {
250 eventId = std::to_string(std::chrono::duration_cast<Microseconds>(HRClock::now().time_since_epoch()).count());
251 }
252
253 EventDelegateToken add(TriggerEventDelegate<RTy, ArgTypes...> eventDelegate) {
254 EventDelegateToken eventToken{};
255 eventToken.handlerId = std::to_string(std::chrono::duration_cast<Microseconds>(HRClock::now().time_since_epoch()).count());
256 eventToken.eventId = eventId;
257 functions[eventToken] = std::move(eventDelegate);
258 return eventToken;
259 }
260
261 void erase(EventDelegateToken eventToken) {
262 if (eventToken.eventId == eventId) {
263 if (functions.contains(eventToken)) {
264 functions.erase(eventToken);
265 }
266 }
267 }
268
269 void operator()(ArgTypes&... args) {
270 for (auto iterator = functions.begin(); iterator != functions.end(); ++iterator) {
271 if (iterator.operator*().second.testFunction(args...)) {
272 iterator.operator*().second.function(args...);
273 functions.erase(iterator);
274 }
275 }
276 return;
277 }
278
279 protected:
280 std::string eventId{};
281 };
282
283}
Event-delegate token, representing an event.
Event-delegate, for representing an event-function to be executed.
EventDelegate(RTy(*functionNew)(ArgTypes...))
Constructor, taking a pointer to a function of type RTy(*)(ArgTypes...) as an argument.
EventDelegate(std::function< RTy(ArgTypes...)> functionNew)
Constructor, taking a std::function<RTy(ArgTypes..)> as an argument.
An event that gets fired depending on the result of a "trigger-function" return value.
TriggerEventDelegate(std::function< RTy(ArgTypes...)> functionNew)
Constructor, taking a std::function<RTy(ArgTypes..)> as an argument.
TriggerEventDelegate(RTy(*functionNew)(ArgTypes...))
Constructor, taking a pointer to a function of type RTy(*)(ArgTypes...) as an argument.