Browse Source

Avoid event dispatcher iterator invalidation (see #45)

Michael Ragazzon 6 years ago
parent
commit
f2d788e74e
1 changed files with 5 additions and 2 deletions
  1. 5 2
      Source/Core/EventDispatcher.cpp

+ 5 - 2
Source/Core/EventDispatcher.cpp

@@ -208,9 +208,12 @@ void EventDispatcher::TriggerEvents(Event& event, DefaultActionPhase default_act
 	else if (phase == EventPhase::Bubble)
 		std::tie(begin, end) = std::equal_range(listeners.begin(), listeners.end(), EventListenerEntry(event.GetId(), nullptr, false), CompareIdPhase());
 
-	for (auto it = begin; it != end; ++it)
+	// Convert to indices. If any listeners are added or removed during ProcessEvent, this guards against iterator invalidation.
+	// Note: The result of listener add/remove may then instead be that a listener is skipped or repeated.
+	const size_t i_end = (size_t)(end - listeners.begin());
+	for (size_t i = (size_t)(begin - listeners.begin()); i < i_end && i < listeners.size(); ++i)
 	{
-		it->listener->ProcessEvent(event);
+		listeners[i].listener->ProcessEvent(event);
 	}
 
 	const bool do_default_action = ((unsigned int)phase & (unsigned int)default_action_phase);