Toast Engine
Loading...
Searching...
No Matches
event.hpp
1
9#pragma once
10
11#include <any>
12#include <functional>
13#include <map>
14#include <memory>
15#include <mutex>
16#include <shared_mutex>
17#include <toast/export.hpp>
18#include <toast/log.hpp>
19#include <type_traits>
20#include <typeindex>
21#include <vector>
22
23namespace event {
24
30void TOAST_API pollEvents() noexcept;
31
33namespace _detail {
36struct TOAST_API IEvent {
37 virtual ~IEvent() = default;
38
39#ifdef DEBUG
40 // std::stacktrace stacktrace;
41#endif
42
43private:
44 friend void TOAST_API event::pollEvents() noexcept;
45 virtual void notify() noexcept = 0;
46};
47
49auto TOAST_API allocate(std::size_t size, std::size_t align) noexcept -> void*;
50}
51
55template<typename T, typename... Args>
56 requires std::is_base_of_v<_detail::IEvent, T>
57void send(Args&&... args) noexcept;
58
77template<typename T>
78struct Event : _detail::IEvent {
79 friend class Listener;
80 friend class ThreadListener;
81 friend struct EventSystem;
82 friend T;
84 using callback_t = std::move_only_function<bool(T&)>;
85 using iterator_t = std::multimap<char, void*, std::greater<>>::iterator;
86
87private:
88 Event() = default;
89
90 static void ensureRegistered() noexcept;
91
95 static auto subscribe(char priority, callback_t&& callback) noexcept -> iterator_t;
96
99 static void unsubscribe(iterator_t it) noexcept;
100
102 void notify() noexcept override;
103};
104
111struct TOAST_API EventSystem {
120 struct EventInfo {
121 std::mutex mutex;
122 std::multimap<char, void*, std::greater<>> callbacks;
123 std::vector<void*> processing;
124 bool cached = false;
125 };
126
128 static std::unordered_map<std::type_index, EventInfo> event_data;
129
131 static std::shared_mutex registration_mutex;
132
134 static void unsubscribeAny(std::type_index type, const std::any& iterator);
135
136 template<typename T>
137 static auto info() noexcept -> EventInfo&;
138
140 static std::mutex pool_mutex;
141
143 static std::unordered_map<std::type_index, std::function<void(std::any)>> unsubscribe_map;
144
147 static std::vector<std::unique_ptr<void, void (*)(void*)>> deletion_queue;
148
150 static std::mutex deletion_mutex;
151
152 template<typename T>
153 static void registerEvent() {
154 static_assert(std::is_base_of_v<Event<T>, T>, "CONTRACT VIOLATION: You Must Inhert as 'struct Derived : Event<Derived>'");
155 std::unique_lock registration_lock(registration_mutex);
156 if (event_data.contains(typeid(T))) {
157 // guard against cross-DLL double-registration; same type can be registered from multiple translation units on Windows
158 return;
159 }
160 TOAST_INFO("Events", "Registering Event Type: {}", typeid(T).name());
161 event_data.emplace( // this is goofy because eventinfo has a mutex inside it
162 std::piecewise_construct,
163 std::forward_as_tuple(typeid(T)),
164 std::forward_as_tuple()
165 );
166
167 EventSystem::unsubscribe_map.emplace(typeid(T), [](const std::any& iter) {
168 auto it = std::any_cast<typename Event<T>::iterator_t>(iter);
169 Event<T>::unsubscribe(it);
170 });
171 }
172};
173
187template<typename T>
189
196template<typename T>
197concept ExposedEvent = requires(const T& e, const typename ProtoTraits<T>::Proto& p) {
198 typename ProtoTraits<T>::Proto;
199 typename ProtoTraits<T>::Event;
200 { ProtoTraits<T>::toProto(e) } -> std::same_as<typename ProtoTraits<T>::Proto>;
201 { ProtoTraits<T>::fromProto(p) } -> std::same_as<typename ProtoTraits<T>::Event>;
202};
203
204// register all exposed events into a registry
205void registerProtoEvents();
206
207}
208
209#include "event.inl"
Satisfied when ProtoTraits<T> is fully specialized with both conversion functions.
Definition event.hpp:197
Public logging interface for the engine.
#define TOAST_INFO(sink,...)
logs an information message
Definition log.hpp:83
Per-type callback registry.
Definition event.hpp:120
Internal dispatch table for the event system.
Definition event.hpp:111
static std::mutex deletion_mutex
Protects the event queue memory pool during concurrent sends.
Definition event.hpp:150
static std::shared_mutex registration_mutex
Guards event_data and unsubscribe_map.
Definition event.hpp:131
static std::unordered_map< std::type_index, EventInfo > event_data
Dispatch table keyed by event type; one entry per registered event type.
Definition event.hpp:128
static std::mutex pool_mutex
Protects the event queue memory pool during concurrent sends.
Definition event.hpp:140
static std::unordered_map< std::type_index, std::function< void(std::any)> > unsubscribe_map
Type-erased unsubscribe functions keyed by event type; used by Listener to erase iterators without th...
Definition event.hpp:143
static std::vector< std::unique_ptr< void, void(*)(void *)> > deletion_queue
Definition event.hpp:147
static void unsubscribeAny(std::type_index type, const std::any &iterator)
Unsubscribes a callback of the given type.
Definition event.cpp:51
std::move_only_function< bool(T &)> callback_t
callbacks that return 'true' are consumed and do not propogate
Definition event.hpp:84
Specialization point that exposes a C++ event type over the C# FFI via protobuf.
Definition event.hpp:188
Definition event.hpp:36