From 1c6515ea669aaaa29bf39e99393c7dd216b9d783 Mon Sep 17 00:00:00 2001 From: jules Date: Mon, 5 May 2014 10:20:38 +0100 Subject: [PATCH] Reworked Value to handle changes on a background thread. --- .../values/juce_Value.cpp | 90 ++++++++----------- .../juce_data_structures/values/juce_Value.h | 13 ++- 2 files changed, 47 insertions(+), 56 deletions(-) diff --git a/modules/juce_data_structures/values/juce_Value.cpp b/modules/juce_data_structures/values/juce_Value.cpp index 477936ea5e..1b67735cb2 100644 --- a/modules/juce_data_structures/values/juce_Value.cpp +++ b/modules/juce_data_structures/values/juce_Value.cpp @@ -22,59 +22,55 @@ ============================================================================== */ -class SharedValueSourceUpdater : public ReferenceCountedObject, - private AsyncUpdater +struct SharedValueSourceUpdater : private AsyncUpdater { public: - SharedValueSourceUpdater() : sourcesBeingIterated (nullptr) {} - ~SharedValueSourceUpdater() { masterReference.clear(); } + SharedValueSourceUpdater() {} void update (Value::ValueSource* const source) { - sourcesNeedingAnUpdate.add (source); + { + const ScopedLock sl (lock); + sourcesNeedingUpdate.addIfNotAlreadyThere (source); + } - if (sourcesBeingIterated == nullptr) - triggerAsyncUpdate(); + triggerAsyncUpdate(); } void valueDeleted (Value::ValueSource* const source) { - sourcesNeedingAnUpdate.removeValue (source); - - if (sourcesBeingIterated != nullptr) - sourcesBeingIterated->removeValue (source); + const ScopedLock sl (lock); + sourcesNeedingUpdate.removeFirstMatchingValue (source); } - WeakReference::Master masterReference; - private: - typedef SortedSet SourceSet; - SourceSet sourcesNeedingAnUpdate; - SourceSet* sourcesBeingIterated; + Array sourcesNeedingUpdate; + CriticalSection lock; void handleAsyncUpdate() override { - const ReferenceCountedObjectPtr localRef (this); + SharedResourcePointer localRef; + int maxCallbacks = sourcesNeedingUpdate.size(); + + for (;;) { - const ScopedValueSetter inside (sourcesBeingIterated, nullptr, nullptr); - int maxLoops = 10; + ReferenceCountedObjectPtr toUpdate; - while (sourcesNeedingAnUpdate.size() > 0) { - if (--maxLoops == 0) - { - triggerAsyncUpdate(); - break; - } + const ScopedLock sl (lock); + toUpdate = sourcesNeedingUpdate.remove (0); + } - SourceSet sources; - sources.swapWith (sourcesNeedingAnUpdate); - sourcesBeingIterated = &sources; + if (toUpdate == nullptr) + break; - for (int i = sources.size(); --i >= 0;) - if (i < sources.size()) - sources.getUnchecked(i)->sendChangeMessage (true); + toUpdate->sendChangeMessage (true); + + if (--maxCallbacks <= 0) + { + triggerAsyncUpdate(); + break; } } } @@ -82,7 +78,10 @@ private: JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedValueSourceUpdater) }; -static WeakReference sharedUpdater; +struct Value::ValueSource::Pimpl +{ + SharedResourcePointer updater; +}; Value::ValueSource::ValueSource() { @@ -90,8 +89,8 @@ Value::ValueSource::ValueSource() Value::ValueSource::~ValueSource() { - if (asyncUpdater != nullptr) - static_cast (asyncUpdater.get())->valueDeleted (this); + if (pimpl != nullptr) + pimpl->updater->valueDeleted (this); } void Value::ValueSource::sendChangeMessage (const bool synchronous) @@ -103,7 +102,6 @@ void Value::ValueSource::sendChangeMessage (const bool synchronous) if (synchronous) { const ReferenceCountedObjectPtr localRef (this); - asyncUpdater = nullptr; for (int i = numListeners; --i >= 0;) if (Value* const v = valuesWithListeners[i]) @@ -111,22 +109,10 @@ void Value::ValueSource::sendChangeMessage (const bool synchronous) } else { - SharedValueSourceUpdater* updater = static_cast (asyncUpdater.get()); + if (pimpl == nullptr) + pimpl = new Pimpl(); - if (updater == nullptr) - { - if (sharedUpdater == nullptr) - { - asyncUpdater = updater = new SharedValueSourceUpdater(); - sharedUpdater = updater; - } - else - { - asyncUpdater = updater = sharedUpdater.get(); - } - } - - updater->update (this); + pimpl->updater->update (this); } } } @@ -195,13 +181,13 @@ Value& Value::operator= (const Value& other) #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS Value::Value (Value&& other) noexcept - : value (static_cast &&> (other.value)) + : value (static_cast&&> (other.value)) { } Value& Value::operator= (Value&& other) noexcept { - value = static_cast &&> (other.value); + value = static_cast&&> (other.value); return *this; } #endif diff --git a/modules/juce_data_structures/values/juce_Value.h b/modules/juce_data_structures/values/juce_Value.h index 5b23e1aed1..a509ab4a83 100644 --- a/modules/juce_data_structures/values/juce_Value.h +++ b/modules/juce_data_structures/values/juce_Value.h @@ -192,8 +192,13 @@ public: protected: //============================================================================== friend class Value; - SortedSet valuesWithListeners; - ReferenceCountedObjectPtr asyncUpdater; + SortedSet valuesWithListeners; + + private: + struct Pimpl; + friend struct Pimpl; + friend struct ContainerDeletePolicy; + ScopedPointer pimpl; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSource) }; @@ -210,8 +215,8 @@ public: private: //============================================================================== friend class ValueSource; - ReferenceCountedObjectPtr value; - ListenerList listeners; + ReferenceCountedObjectPtr value; + ListenerList listeners; void callListeners();