Loading...
Searching...
No Matches
juce_ListenerList.h
/*
==============================================================================
This file is part of the JUCE library.
Copyright (c) 2022 - Raw Material Software Limited
JUCE is an open source library subject to commercial or open-source
licensing.
The code included in this file is provided under the terms of the ISC license
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
To use, copy, modify, and/or distribute this software for any purpose with or
without fee is hereby granted provided that the above copyright notice and
this permission notice appear in all copies.
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
DISCLAIMED.
==============================================================================
*/
namespace juce
{
//==============================================================================
template <class ListenerClass,
class ArrayType = Array<ListenerClass*>>
class ListenerList
{
public:
//==============================================================================
ListenerList() = default;
~ListenerList() { clear(); }
//==============================================================================
void add (ListenerClass* listenerToAdd)
{
if (listenerToAdd != nullptr)
listeners->addIfNotAlreadyThere (listenerToAdd);
else
jassertfalse; // Listeners can't be null pointers!
}
void remove (ListenerClass* listenerToRemove)
{
jassert (listenerToRemove != nullptr); // Listeners can't be null pointers!
const ScopedLockType lock (listeners->getLock());
if (const auto index = listeners->removeFirstMatchingValue (listenerToRemove); index >= 0)
{
for (auto* it : *iterators)
{
--it->end;
if (index <= it->index)
--it->index;
}
}
}
ErasedScopeGuard addScoped (ListenerClass& listenerToAdd)
{
add (&listenerToAdd);
return ErasedScopeGuard { [this, &listenerToAdd] { remove (&listenerToAdd); } };
}
int size() const noexcept { return listeners->size(); }
bool isEmpty() const noexcept { return listeners->isEmpty(); }
void clear()
{
const ScopedLockType lock (listeners->getLock());
listeners->clear();
for (auto* it : *iterators)
it->end = 0;
}
bool contains (ListenerClass* listener) const noexcept { return listeners->contains (listener); }
const ArrayType& getListeners() const noexcept { return *listeners; }
//==============================================================================
template <typename Callback>
void call (Callback&& callback)
{
callCheckedExcluding (nullptr,
DummyBailOutChecker{},
std::forward<Callback> (callback));
}
template <typename Callback>
void callExcluding (ListenerClass* listenerToExclude, Callback&& callback)
{
callCheckedExcluding (listenerToExclude,
DummyBailOutChecker{},
std::forward<Callback> (callback));
}
template <typename Callback, typename BailOutCheckerType>
void callChecked (const BailOutCheckerType& bailOutChecker, Callback&& callback)
{
callCheckedExcluding (nullptr,
bailOutChecker,
std::forward<Callback> (callback));
}
template <typename Callback, typename BailOutCheckerType>
void callCheckedExcluding (ListenerClass* listenerToExclude,
const BailOutCheckerType& bailOutChecker,
Callback&& callback)
{
const auto localListeners = listeners;
const ScopedLockType lock { localListeners->getLock() };
Iterator it{};
it.end = localListeners->size();
iterators->push_back (&it);
const ScopeGuard scope { [i = iterators, &it]
{
i->erase (std::remove (i->begin(), i->end(), &it), i->end());
} };
for (; it.index < it.end; ++it.index)
{
if (bailOutChecker.shouldBailOut())
return;
auto* listener = localListeners->getUnchecked (it.index);
if (listener == listenerToExclude)
continue;
callback (*listener);
}
}
//==============================================================================
template <typename... MethodArgs, typename... Args>
void call (void (ListenerClass::*callbackFunction) (MethodArgs...), Args&&... args)
{
callCheckedExcluding (nullptr,
DummyBailOutChecker{},
callbackFunction,
std::forward<Args> (args)...);
}
template <typename... MethodArgs, typename... Args>
void callExcluding (ListenerClass* listenerToExclude,
void (ListenerClass::*callbackFunction) (MethodArgs...),
Args&&... args)
{
callCheckedExcluding (listenerToExclude,
DummyBailOutChecker{},
callbackFunction,
std::forward<Args> (args)...);
}
template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
void callChecked (const BailOutCheckerType& bailOutChecker,
void (ListenerClass::*callbackFunction) (MethodArgs...),
Args&&... args)
{
callCheckedExcluding (nullptr,
bailOutChecker,
callbackFunction,
std::forward<Args> (args)...);
}
template <typename BailOutCheckerType, typename... MethodArgs, typename... Args>
void callCheckedExcluding (ListenerClass* listenerToExclude,
const BailOutCheckerType& bailOutChecker,
void (ListenerClass::*callbackFunction) (MethodArgs...),
Args&&... args)
{
callCheckedExcluding (listenerToExclude, bailOutChecker, [&] (ListenerClass& l)
{
(l.*callbackFunction) (args...);
});
}
//==============================================================================
struct DummyBailOutChecker
{
constexpr bool shouldBailOut() const noexcept { return false; }
};
//==============================================================================
using ThisType = ListenerList<ListenerClass, ArrayType>;
using ListenerType = ListenerClass;
private:
//==============================================================================
using ScopedLockType = typename ArrayType::ScopedLockType;
//==============================================================================
using SharedListeners = std::shared_ptr<ArrayType>;
const SharedListeners listeners = std::make_shared<ArrayType>();
struct Iterator
{
int index{};
int end{};
};
using SafeIterators = std::vector<Iterator*>;
using SharedIterators = std::shared_ptr<SafeIterators>;
const SharedIterators iterators = std::make_shared<SafeIterators>();
//==============================================================================
JUCE_DECLARE_NON_COPYABLE (ListenerList)
};
} // namespace juce
juce::Array
Definition juce_Array.h:56
juce::ErasedScopeGuard
Definition juce_ScopeGuard.h:77
juce::ListenerList::callChecked
void callChecked(const BailOutCheckerType &bailOutChecker, Callback &&callback)
Definition juce_ListenerList.h:207
juce::ListenerList::isEmpty
bool isEmpty() const noexcept
Definition juce_ListenerList.h:148
juce::ListenerList::callCheckedExcluding
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, Callback &&callback)
Definition juce_ListenerList.h:221
juce::ListenerList::callChecked
void callChecked(const BailOutCheckerType &bailOutChecker, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
Definition juce_ListenerList.h:283
juce::ListenerList::call
void call(Callback &&callback)
Definition juce_ListenerList.h:182
juce::ListenerList::callExcluding
void callExcluding(ListenerClass *listenerToExclude, Callback &&callback)
Definition juce_ListenerList.h:193
juce::ListenerList::callCheckedExcluding
void callCheckedExcluding(ListenerClass *listenerToExclude, const BailOutCheckerType &bailOutChecker, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
Definition juce_ListenerList.h:300
juce::ListenerList::call
void call(void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
Definition juce_ListenerList.h:255
juce::ListenerList::add
void add(ListenerClass *listenerToAdd)
Definition juce_ListenerList.h:100
juce::ListenerList::addScoped
ErasedScopeGuard addScoped(ListenerClass &listenerToAdd)
Definition juce_ListenerList.h:138
juce::ListenerList::remove
void remove(ListenerClass *listenerToRemove)
Definition juce_ListenerList.h:114
juce::ListenerList::contains
bool contains(ListenerClass *listener) const noexcept
Definition juce_ListenerList.h:166
juce::ListenerList::size
int size() const noexcept
Definition juce_ListenerList.h:145
juce::ListenerList::ListenerList
ListenerList()=default
juce::ListenerList::callExcluding
void callExcluding(ListenerClass *listenerToExclude, void(ListenerClass::*callbackFunction)(MethodArgs...), Args &&... args)
Definition juce_ListenerList.h:267
juce::ListenerList::getListeners
const ArrayType & getListeners() const noexcept
Definition juce_ListenerList.h:177
juce::ListenerList::clear
void clear()
Definition juce_ListenerList.h:155
juce::ListenerList::~ListenerList
~ListenerList()
Definition juce_ListenerList.h:88
juce::ListenerList::DummyBailOutChecker
Definition juce_ListenerList.h:316
juce::ScopeGuard
Definition juce_ScopeGuard.h:52