1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

ListenerList: Optimise empty listener list

This commit is contained in:
Anthony Nicholls 2024-06-01 01:25:13 +01:00
parent 315167a91a
commit 0dfff1454c

View file

@ -111,6 +111,8 @@ public:
*/
void add (ListenerClass* listenerToAdd)
{
initialiseIfNeeded();
if (listenerToAdd != nullptr)
listeners->addIfNotAlreadyThere (listenerToAdd);
else
@ -127,6 +129,9 @@ public:
{
jassert (listenerToRemove != nullptr); // Listeners can't be null pointers!
if (! initialised())
return;
const ScopedLockType lock (listeners->getLock());
if (const auto index = listeners->removeFirstMatchingValue (listenerToRemove); index >= 0)
@ -154,10 +159,10 @@ public:
}
/** Returns the number of registered listeners. */
int size() const noexcept { return listeners->size(); }
int size() const noexcept { return ! initialised() ? 0 : listeners->size(); }
/** Returns true if no listeners are registered, false otherwise. */
bool isEmpty() const noexcept { return listeners->isEmpty(); }
bool isEmpty() const noexcept { return ! initialised() || listeners->isEmpty(); }
/** Clears the list.
@ -166,7 +171,8 @@ public:
*/
void clear()
{
const ScopedLockType lock (listeners->getLock());
if (! initialised())
return;
listeners->clear();
@ -175,7 +181,11 @@ public:
}
/** Returns true if the specified listener has been added to the list. */
bool contains (ListenerClass* listener) const noexcept { return listeners->contains (listener); }
bool contains (ListenerClass* listener) const noexcept
{
return initialised()
&& listeners->contains (listener);
}
/** Returns the raw array of listeners.
@ -186,7 +196,11 @@ public:
@see add, remove, clear, contains
*/
const ArrayType& getListeners() const noexcept { return *listeners; }
const ArrayType& getListeners() const noexcept
{
const_cast<ListenerList*> (this)->initialiseIfNeeded();
return *listeners;
}
//==============================================================================
/** Calls an invokable object for each listener in the list. */
@ -234,6 +248,9 @@ public:
const BailOutCheckerType& bailOutChecker,
Callback&& callback)
{
if (! initialised())
return;
const auto localListeners = listeners;
const ScopedLockType lock { localListeners->getLock() };
@ -339,7 +356,7 @@ private:
//==============================================================================
using SharedListeners = std::shared_ptr<ArrayType>;
const SharedListeners listeners = std::make_shared<ArrayType>();
SharedListeners listeners;
struct Iterator
{
@ -349,7 +366,37 @@ private:
using SafeIterators = std::vector<Iterator*>;
using SharedIterators = std::shared_ptr<SafeIterators>;
const SharedIterators iterators = std::make_shared<SafeIterators>();
SharedIterators iterators;
enum class State
{
uninitialised,
initialising,
initialised
};
std::atomic<State> state { State::uninitialised };
inline bool initialised() const noexcept { return state == State::initialised; }
inline void initialiseIfNeeded() noexcept
{
if (initialised())
return;
auto expected = State::uninitialised;
if (state.compare_exchange_strong (expected, State::initialising))
{
listeners = std::make_shared<ArrayType>();
iterators = std::make_shared<SafeIterators>();
state = State::initialised;
return;
}
while (! initialised())
std::this_thread::yield();
}
//==============================================================================
JUCE_DECLARE_NON_COPYABLE (ListenerList)