OpenShot Library | libopenshot-audio 0.2.0
juce_ListenerList.h
1
2/** @weakgroup juce_core-containers
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/**
32 Holds a set of objects and can invoke a member function callback on each object
33 in the set with a single call.
34
35 Use a ListenerList to manage a set of objects which need a callback, and you
36 can invoke a member function by simply calling call() or callChecked().
37
38 E.g.
39 @code
40 class MyListenerType
41 {
42 public:
43 void myCallbackMethod (int foo, bool bar);
44 };
45
46 ListenerList<MyListenerType> listeners;
47 listeners.add (someCallbackObjects...);
48
49 // This will invoke myCallbackMethod (1234, true) on each of the objects
50 // in the list...
51 listeners.call ([] (MyListenerType& l) { l.myCallbackMethod (1234, true); });
52 @endcode
53
54 If you add or remove listeners from the list during one of the callbacks - i.e. while
55 it's in the middle of iterating the listeners, then it's guaranteed that no listeners
56 will be mistakenly called after they've been removed, but it may mean that some of the
57 listeners could be called more than once, or not at all, depending on the list's order.
58
59 Sometimes, there's a chance that invoking one of the callbacks might result in the
60 list itself being deleted while it's still iterating - to survive this situation, you can
61 use callChecked() instead of call(), passing it a local object to act as a "BailOutChecker".
62 The BailOutChecker must implement a method of the form "bool shouldBailOut()", and
63 the list will check this after each callback to determine whether it should abort the
64 operation. For an example of a bail-out checker, see the Component::BailOutChecker class,
65 which can be used to check when a Component has been deleted. See also
66 ListenerList::DummyBailOutChecker, which is a dummy checker that always returns false.
67
68 @tags{Core}
69*/
70template <class ListenerClass,
71 class ArrayType = Array<ListenerClass*>>
73{
74public:
75 //==============================================================================
76 /** Creates an empty list. */
77 ListenerList() = default;
78
79 /** Destructor. */
80 ~ListenerList() = default;
81
82 //==============================================================================
83 /** Adds a listener to the list.
84 A listener can only be added once, so if the listener is already in the list,
85 this method has no effect.
86 @see remove
87 */
89 {
90 if (listenerToAdd != nullptr)
92 else
93 jassertfalse; // Listeners can't be null pointers!
94 }
95
96 /** Removes a listener from the list.
97 If the listener wasn't in the list, this has no effect.
98 */
100 {
101 jassert (listenerToRemove != nullptr); // Listeners can't be null pointers!
103 }
104
105 /** Returns the number of registered listeners. */
106 int size() const noexcept { return listeners.size(); }
107
108 /** Returns true if no listeners are registered, false otherwise. */
109 bool isEmpty() const noexcept { return listeners.isEmpty(); }
110
111 /** Clears the list. */
112 void clear() { listeners.clear(); }
113
114 /** Returns true if the specified listener has been added to the list. */
115 bool contains (ListenerClass* listener) const noexcept { return listeners.contains (listener); }
116
117 /** Returns the raw array of listeners. */
118 const ArrayType& getListeners() const noexcept { return listeners; }
119
120 //==============================================================================
121 /** Calls a member function on each listener in the list, with multiple parameters. */
122 template <typename Callback>
123 void call (Callback&& callback)
124 {
125 typename ArrayType::ScopedLockType lock (listeners.getLock());
126
128 callback (*iter.getListener());
129 }
130
131 /** Calls a member function with 1 parameter, on all but the specified listener in the list.
132 This can be useful if the caller is also a listener and needs to exclude itself.
133 */
134 template <typename Callback>
135 void callExcluding (ListenerClass* listenerToExclude, Callback&& callback)
136 {
137 typename ArrayType::ScopedLockType lock (listeners.getLock());
138
140 {
141 auto* l = iter.getListener();
142
143 if (l != listenerToExclude)
144 callback (*l);
145 }
146 }
147
148 /** Calls a member function on each listener in the list, with 1 parameter and a bail-out-checker.
149 See the class description for info about writing a bail-out checker.
150 */
151 template <typename Callback, typename BailOutCheckerType>
152 void callChecked (const BailOutCheckerType& bailOutChecker, Callback&& callback)
153 {
154 typename ArrayType::ScopedLockType lock (listeners.getLock());
155
157 callback (*iter.getListener());
158 }
159
160 /** Calls a member function, with 1 parameter, on all but the specified listener in the list
161 with a bail-out-checker. This can be useful if the caller is also a listener and needs to
162 exclude itself. See the class description for info about writing a bail-out checker.
163 */
164 template <typename Callback, typename BailOutCheckerType>
167 Callback&& callback)
168 {
169 typename ArrayType::ScopedLockType lock (listeners.getLock());
170
172 {
173 auto* l = iter.getListener();
174
175 if (l != listenerToExclude)
176 callback (*l);
177 }
178 }
179
180 //==============================================================================
181 /** A dummy bail-out checker that always returns false.
182 See the ListenerList notes for more info about bail-out checkers.
183 */
185 {
186 bool shouldBailOut() const noexcept { return false; }
187 };
188
191
192 //==============================================================================
193 /** Iterates the listeners in a ListenerList. */
194 template <class BailOutCheckerType, class ListType>
195 struct Iterator
196 {
198 : list (listToIterate), index (listToIterate.size())
199 {}
200
201 ~Iterator() = default;
202
203 //==============================================================================
204 bool next() noexcept
205 {
206 if (index <= 0)
207 return false;
208
209 auto listSize = list.size();
210
211 if (--index < listSize)
212 return true;
213
214 index = listSize - 1;
215 return index >= 0;
216 }
217
218 bool next (const BailOutCheckerType& bailOutChecker) noexcept
219 {
220 return (! bailOutChecker.shouldBailOut()) && next();
221 }
222
223 typename ListType::ListenerType* getListener() const noexcept
224 {
225 return list.getListeners().getUnchecked (index);
226 }
227
228 //==============================================================================
229 private:
230 const ListType& list;
231 int index;
232
233 JUCE_DECLARE_NON_COPYABLE (Iterator)
234 };
235
236 //==============================================================================
237 #ifndef DOXYGEN
238 // There are now lambda-based call functions that can be used to replace these old method-based versions.
239 // We'll eventually deprecate these old ones, so please begin moving your code to use lambdas!
240 void call (void (ListenerClass::*callbackFunction) ())
241 {
242 call ([=] (ListenerClass& l) { (l.*callbackFunction)(); });
243 }
244
245 void callExcluding (ListenerClass* listenerToExclude, void (ListenerClass::*callbackFunction) ())
246 {
247 callExcluding (listenerToExclude, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
248 }
249
250 template <class BailOutCheckerType>
251 void callChecked (const BailOutCheckerType& bailOutChecker, void (ListenerClass::*callbackFunction) ())
252 {
253 callChecked (bailOutChecker, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
254 }
255
256 template <class BailOutCheckerType>
257 void callCheckedExcluding (ListenerClass* listenerToExclude,
258 const BailOutCheckerType& bailOutChecker,
259 void (ListenerClass::*callbackFunction) ())
260 {
261 callCheckedExcluding (listenerToExclude, bailOutChecker, [=] (ListenerClass& l) { (l.*callbackFunction)(); });
262 }
263
264 template <typename... MethodArgs, typename... Args>
265 void call (void (ListenerClass::*callbackFunction) (MethodArgs...), Args&&... args)
266 {
267 typename ArrayType::ScopedLockType lock (listeners.getLock());
268
269 for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
270 (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
271 }
272
273 template <typename... MethodArgs, typename... Args>
274 void callExcluding (ListenerClass* listenerToExclude,
275 void (ListenerClass::*callbackFunction) (MethodArgs...),
276 Args&&... args)
277 {
278 typename ArrayType::ScopedLockType lock (listeners.getLock());
279
280 for (Iterator<DummyBailOutChecker, ThisType> iter (*this); iter.next();)
281 if (iter.getListener() != listenerToExclude)
282 (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
283 }
284
285 template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
286 void callChecked (const BailOutCheckerType& bailOutChecker,
287 void (ListenerClass::*callbackFunction) (MethodArgs...),
288 Args&&... args)
289 {
290 typename ArrayType::ScopedLockType lock (listeners.getLock());
291
292 for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
293 (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
294 }
295
296 template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
297 void callCheckedExcluding (ListenerClass* listenerToExclude,
298 const BailOutCheckerType& bailOutChecker,
299 void (ListenerClass::*callbackFunction) (MethodArgs...),
300 Args&&... args)
301 {
302 typename ArrayType::ScopedLockType lock (listeners.getLock());
303
304 for (Iterator<BailOutCheckerType, ThisType> iter (*this); iter.next (bailOutChecker);)
305 if (iter.getListener() != listenerToExclude)
306 (iter.getListener()->*callbackFunction) (static_cast<typename TypeHelpers::ParameterType<Args>::type> (args)...);
307 }
308 #endif
309
310private:
311 //==============================================================================
312 ArrayType listeners;
313
314 JUCE_DECLARE_NON_COPYABLE (ListenerList)
315};
316
317} // namespace juce
318
319/** @}*/
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:60
ElementType getUnchecked(int index) const
Returns one of the elements in the array, without checking the index passed in.
Definition juce_Array.h:256
bool isEmpty() const noexcept
Returns true if the array is empty, false otherwise.
Definition juce_Array.h:226
const TypeOfCriticalSectionToUse & getLock() const noexcept
Returns the CriticalSection that locks this array.
int size() const noexcept
Returns the current number of elements in the array.
Definition juce_Array.h:219
void removeFirstMatchingValue(ParameterType valueToRemove)
Removes an item from the array.
Definition juce_Array.h:791
bool contains(ParameterType elementToLookFor) const
Returns true if the array contains at least one occurrence of an object.
Definition juce_Array.h:357
void clear()
Removes all elements from the array.
Definition juce_Array.h:192
bool addIfNotAlreadyThere(ParameterType newElement)
Appends a new element at the end of the array as long as the array doesn't already contain it.
Definition juce_Array.h:479
Holds a set of objects and can invoke a member function callback on each object in the set with a sin...
~ListenerList()=default
Destructor.
void callChecked(const BailOutCheckerType &bailOutChecker, Callback &&callback)
Calls a member function on each listener in the list, with 1 parameter and a bail-out-checker.
bool isEmpty() const noexcept
Returns true if no listeners are registered, false otherwise.
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, Callback &&callback)
Calls a member function, with 1 parameter, on all but the specified listener in the list with a bail-...
void call(Callback &&callback)
Calls a member function on each listener in the list, with multiple parameters.
void callExcluding(ListenerClass *listenerToExclude, Callback &&callback)
Calls a member function with 1 parameter, on all but the specified listener in the list.
void add(ListenerClass *listenerToAdd)
Adds a listener to the list.
void remove(ListenerClass *listenerToRemove)
Removes a listener from the list.
bool contains(ListenerClass *listener) const noexcept
Returns true if the specified listener has been added to the list.
int size() const noexcept
Returns the number of registered listeners.
ListenerList()=default
Creates an empty list.
const ArrayType & getListeners() const noexcept
Returns the raw array of listeners.
void clear()
Clears the list.
A dummy bail-out checker that always returns false.
Iterates the listeners in a ListenerList.