4
4
5
5
// ////////////////// Funcs ////////////////////
6
6
7
+ struct EventListener ;
8
+
7
9
void InitBasicEventListeners ();
8
10
void EnableEventListener (int eventId);
9
-
10
- bool LLSEAddEventListener (ScriptEngine* engine, const std::string& eventName, const Local<Function>& func);
11
+ optional_ref<EventListener>
12
+ LLSEAddEventListener (ScriptEngine* engine, const std::string& eventName, const Local<Function>& func);
11
13
bool LLSERemoveAllEventListeners (ScriptEngine* engine);
12
14
bool LLSECallEventsOnHotLoad (ScriptEngine* engine);
13
15
bool LLSECallEventsOnUnload (ScriptEngine* engine);
@@ -118,13 +120,36 @@ enum class EVENT_TYPES : int {
118
120
119
121
// ////////////////// Listeners ////////////////////
120
122
121
- struct ListenerListType {
123
+ inline std::set<EVENT_TYPES> dirtyEventTypes{};
124
+
125
+ struct EventListener {
122
126
ScriptEngine* engine;
123
127
script::Global<Function> func;
128
+ // mark as removed and remove at next tick
129
+ using RemovedRef = std::shared_ptr<std::reference_wrapper<bool >>;
130
+ EVENT_TYPES type;
131
+ bool removed = false ;
132
+ RemovedRef removedRef{std::make_shared<RemovedRef::element_type>(std::ref (removed))};
133
+
134
+ [[nodiscard]] inline auto remover () const {
135
+ return [ref{RemovedRef::weak_type{removedRef}}, type{type}]() -> bool {
136
+ auto removed = ref.lock ();
137
+ if (removed) {
138
+ removed->get () = true ;
139
+ dirtyEventTypes.emplace (type);
140
+ }
141
+ return !!removed;
142
+ };
143
+ }
144
+ EventListener (ScriptEngine* engine, script::Global<Function> func, EVENT_TYPES type)
145
+ : engine(engine),
146
+ func (std::move(func)),
147
+ type(type) {};
148
+ EventListener (const EventListener&) = delete;
124
149
};
125
150
126
151
// 监听器表
127
- extern std::list<ListenerListType > listenerList[int (EVENT_TYPES::EVENT_COUNT)];
152
+ extern std::list<EventListener > listenerList[int (EVENT_TYPES::EVENT_COUNT)];
128
153
129
154
// 监听器历史
130
155
extern bool hasListened[int (EVENT_TYPES::EVENT_COUNT)];
@@ -134,17 +159,17 @@ inline std::string EventTypeToString(EVENT_TYPES e) { return std::string(magic_e
134
159
135
160
#define CallEvent (type, ...) \
136
161
[&]() { \
137
- std::list<ListenerListType >& nowList = listenerList[(int )type]; \
138
- bool returnValue = true ; \
139
- for (auto & listener : nowList) { \
162
+ std::list<EventListener >& nowList = listenerList[(int )type]; \
163
+ bool returnValue = true ; \
164
+ for (auto & listener : nowList | std::views::filter ([]( auto & l) { return !l. removed ; })) { \
140
165
EngineScope enter (listener.engine ); \
141
166
CallEventImpl (listener, returnValue, type, __VA_ARGS__); \
142
167
} \
143
168
return returnValue; \
144
169
}()
145
170
146
171
template <typename ... T>
147
- void CallEventImpl (ListenerListType & listener, bool & returnValue, EVENT_TYPES type, T&&... args) {
172
+ void CallEventImpl (EventListener & listener, bool & returnValue, EVENT_TYPES type, T&&... args) {
148
173
try {
149
174
auto result = listener.func .get ().call ({}, args...);
150
175
if (result.isBoolean () && result.asBoolean ().value () == false ) {
@@ -168,14 +193,14 @@ void CallEventImpl(ListenerListType& listener, bool& returnValue, EVENT_TYPES ty
168
193
}
169
194
170
195
#define FakeCallEvent (engine, type, ...) \
171
- std::list<ListenerListType >& nowList = listenerList[(int )type]; \
172
- for (auto & listener : nowList) { \
196
+ std::list<EventListener >& nowList = listenerList[(int )type]; \
197
+ for (auto & listener : nowList | std::views::filter([]( auto & l) { return !l. removed ; })) { \
173
198
EngineScope enter (listener.engine ); \
174
199
FakeCallEventImpl (listener, engine, type, __VA_ARGS__); \
175
200
}
176
201
177
202
template <typename ... T>
178
- void FakeCallEventImpl (ListenerListType & listener, ScriptEngine* engine, EVENT_TYPES type, T&&... args) {
203
+ void FakeCallEventImpl (EventListener & listener, ScriptEngine* engine, EVENT_TYPES type, T&&... args) {
179
204
if (listener.engine == engine) {
180
205
try {
181
206
listener.func .get ().call ({}, args...);
0 commit comments