OpenShot Audio Library | OpenShotAudio  0.6.0
juce_ListenerList.h
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2022 - Raw Material Software Limited
6 
7  JUCE is an open source library subject to commercial or open-source
8  licensing.
9 
10  The code included in this file is provided under the terms of the ISC license
11  http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12  To use, copy, modify, and/or distribute this software for any purpose with or
13  without fee is hereby granted provided that the above copyright notice and
14  this permission notice appear in all copies.
15 
16  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18  DISCLAIMED.
19 
20  ==============================================================================
21 */
22 
23 namespace juce
24 {
25 
26 //==============================================================================
78 template <class ListenerClass,
79  class ArrayType = Array<ListenerClass*>>
81 {
82 public:
83  //==============================================================================
85  ListenerList() = default;
86 
89 
90  //==============================================================================
100  void add (ListenerClass* listenerToAdd)
101  {
102  if (listenerToAdd != nullptr)
103  listeners->addIfNotAlreadyThere (listenerToAdd);
104  else
105  jassertfalse; // Listeners can't be null pointers!
106  }
107 
114  void remove (ListenerClass* listenerToRemove)
115  {
116  jassert (listenerToRemove != nullptr); // Listeners can't be null pointers!
117 
118  const ScopedLockType lock (listeners->getLock());
119 
120  if (const auto index = listeners->removeFirstMatchingValue (listenerToRemove); index >= 0)
121  {
122  for (auto* it : *iterators)
123  {
124  --it->end;
125 
126  if (index <= it->index)
127  --it->index;
128  }
129  }
130  }
131 
138  ErasedScopeGuard addScoped (ListenerClass& listenerToAdd)
139  {
140  add (&listenerToAdd);
141  return ErasedScopeGuard { [this, &listenerToAdd] { remove (&listenerToAdd); } };
142  }
143 
145  int size() const noexcept { return listeners->size(); }
146 
148  bool isEmpty() const noexcept { return listeners->isEmpty(); }
149 
155  void clear()
156  {
157  const ScopedLockType lock (listeners->getLock());
158 
159  listeners->clear();
160 
161  for (auto* it : *iterators)
162  it->end = 0;
163  }
164 
166  bool contains (ListenerClass* listener) const noexcept { return listeners->contains (listener); }
167 
177  const ArrayType& getListeners() const noexcept { return *listeners; }
178 
179  //==============================================================================
181  template <typename Callback>
182  void call (Callback&& callback)
183  {
184  callCheckedExcluding (nullptr,
186  std::forward<Callback> (callback));
187  }
188 
192  template <typename Callback>
193  void callExcluding (ListenerClass* listenerToExclude, Callback&& callback)
194  {
195  callCheckedExcluding (listenerToExclude,
197  std::forward<Callback> (callback));
198 
199  }
200 
206  template <typename Callback, typename BailOutCheckerType>
207  void callChecked (const BailOutCheckerType& bailOutChecker, Callback&& callback)
208  {
209  callCheckedExcluding (nullptr,
210  bailOutChecker,
211  std::forward<Callback> (callback));
212  }
213 
220  template <typename Callback, typename BailOutCheckerType>
221  void callCheckedExcluding (ListenerClass* listenerToExclude,
222  const BailOutCheckerType& bailOutChecker,
223  Callback&& callback)
224  {
225  const auto localListeners = listeners;
226  const ScopedLockType lock { localListeners->getLock() };
227 
228  Iterator it{};
229  it.end = localListeners->size();
230 
231  iterators->push_back (&it);
232 
233  const ScopeGuard scope { [i = iterators, &it]
234  {
235  i->erase (std::remove (i->begin(), i->end(), &it), i->end());
236  } };
237 
238  for (; it.index < it.end; ++it.index)
239  {
240  if (bailOutChecker.shouldBailOut())
241  return;
242 
243  auto* listener = localListeners->getUnchecked (it.index);
244 
245  if (listener == listenerToExclude)
246  continue;
247 
248  callback (*listener);
249  }
250  }
251 
252  //==============================================================================
254  template <typename... MethodArgs, typename... Args>
255  void call (void (ListenerClass::*callbackFunction) (MethodArgs...), Args&&... args)
256  {
257  callCheckedExcluding (nullptr,
259  callbackFunction,
260  std::forward<Args> (args)...);
261  }
262 
266  template <typename... MethodArgs, typename... Args>
267  void callExcluding (ListenerClass* listenerToExclude,
268  void (ListenerClass::*callbackFunction) (MethodArgs...),
269  Args&&... args)
270  {
271  callCheckedExcluding (listenerToExclude,
273  callbackFunction,
274  std::forward<Args> (args)...);
275  }
276 
282  template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
283  void callChecked (const BailOutCheckerType& bailOutChecker,
284  void (ListenerClass::*callbackFunction) (MethodArgs...),
285  Args&&... args)
286  {
287  callCheckedExcluding (nullptr,
288  bailOutChecker,
289  callbackFunction,
290  std::forward<Args> (args)...);
291  }
292 
299  template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
300  void callCheckedExcluding (ListenerClass* listenerToExclude,
301  const BailOutCheckerType& bailOutChecker,
302  void (ListenerClass::*callbackFunction) (MethodArgs...),
303  Args&&... args)
304  {
305  callCheckedExcluding (listenerToExclude, bailOutChecker, [&] (ListenerClass& l)
306  {
307  (l.*callbackFunction) (args...);
308  });
309  }
310 
311  //==============================================================================
316  {
317  constexpr bool shouldBailOut() const noexcept { return false; }
318  };
319 
320  //==============================================================================
322  using ListenerType = ListenerClass;
323 
324 private:
325  //==============================================================================
326  using ScopedLockType = typename ArrayType::ScopedLockType;
327 
328  //==============================================================================
329  using SharedListeners = std::shared_ptr<ArrayType>;
330  const SharedListeners listeners = std::make_shared<ArrayType>();
331 
332  struct Iterator
333  {
334  int index{};
335  int end{};
336  };
337 
338  using SafeIterators = std::vector<Iterator*>;
339  using SharedIterators = std::shared_ptr<SafeIterators>;
340  const SharedIterators iterators = std::make_shared<SafeIterators>();
341 
342  //==============================================================================
343  JUCE_DECLARE_NON_COPYABLE (ListenerList)
344 };
345 
346 } // namespace juce
void callChecked(const BailOutCheckerType &bailOutChecker, Callback &&callback)
const ArrayType & getListeners() const noexcept
bool isEmpty() const noexcept
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, Callback &&callback)
void callChecked(const BailOutCheckerType &bailOutChecker, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
void call(Callback &&callback)
void callExcluding(ListenerClass *listenerToExclude, Callback &&callback)
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
void call(void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
void add(ListenerClass *listenerToAdd)
ErasedScopeGuard addScoped(ListenerClass &listenerToAdd)
void remove(ListenerClass *listenerToRemove)
bool contains(ListenerClass *listener) const noexcept
int size() const noexcept
ListenerList()=default
void callExcluding(ListenerClass *listenerToExclude, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)