From 06fb8f4ea29c179a68d4c46525e5a183441e61da Mon Sep 17 00:00:00 2001 From: Anthony Nicholls Date: Tue, 25 Jun 2024 09:36:05 +0100 Subject: [PATCH] ListenerList: Fix a bug where removing a listener during a callback in which it had also been added prevents other listeners from being called --- .../juce_core/containers/juce_ListenerList.h | 3 +- .../containers/juce_ListenerList_test.cpp | 54 +++++++++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/modules/juce_core/containers/juce_ListenerList.h b/modules/juce_core/containers/juce_ListenerList.h index ee8ec18041..563921951c 100644 --- a/modules/juce_core/containers/juce_ListenerList.h +++ b/modules/juce_core/containers/juce_ListenerList.h @@ -135,7 +135,8 @@ public: { for (auto* it : *iterators) { - --it->end; + if (index < it->end) + --it->end; if (index <= it->index) --it->index; diff --git a/modules/juce_core/containers/juce_ListenerList_test.cpp b/modules/juce_core/containers/juce_ListenerList_test.cpp index 6466778ee5..8df2d5a81e 100644 --- a/modules/juce_core/containers/juce_ListenerList_test.cpp +++ b/modules/juce_core/containers/juce_ListenerList_test.cpp @@ -431,25 +431,59 @@ public: ListenerList listeners; expect (listeners.size() == 0); - Listener listener; - listeners.add (&listener); - expect (listeners.size() == 1); + Listener listener1; + Listener listener2; + listeners.add (&listener1); + listeners.add (&listener2); + expect (listeners.size() == 2); - bool listenerCalled = false; + int numberOfCallbacks = 0; listeners.call ([&] (auto& l) { listeners.remove (&l); - expect (listeners.size() == 0); - - listeners.add (&l); expect (listeners.size() == 1); - listenerCalled = true; + listeners.add (&l); + expect (listeners.size() == 2); + + ++numberOfCallbacks; }); - expect (listenerCalled); - expect (listeners.size() == 1); + expect (numberOfCallbacks == 2); + expect (listeners.size() == 2); + } + + beginTest ("Add and remove a nested listener"); + { + struct Listener{}; + + ListenerList listeners; + expect (listeners.size() == 0); + + Listener listener1; + Listener listener2; + listeners.add (&listener1); + listeners.add (&listener2); + expect (listeners.size() == 2); + + int numberOfCallbacks = 0; + + listeners.call ([&] (auto) + { + Listener nestedListener; + + listeners.add (&nestedListener); + expect (listeners.size() == 3); + + listeners.remove (&nestedListener); + expect (listeners.size() == 2); + + ++numberOfCallbacks; + }); + + expect (numberOfCallbacks == 2); + expect (listeners.size() == 2); } }