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

Reworked Value to handle changes on a background thread.

This commit is contained in:
jules 2014-05-05 10:20:38 +01:00
parent 27046fd1a7
commit 1c6515ea66
2 changed files with 47 additions and 56 deletions

View file

@ -22,59 +22,55 @@
============================================================================== ==============================================================================
*/ */
class SharedValueSourceUpdater : public ReferenceCountedObject, struct SharedValueSourceUpdater : private AsyncUpdater
private AsyncUpdater
{ {
public: public:
SharedValueSourceUpdater() : sourcesBeingIterated (nullptr) {} SharedValueSourceUpdater() {}
~SharedValueSourceUpdater() { masterReference.clear(); }
void update (Value::ValueSource* const source) 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) void valueDeleted (Value::ValueSource* const source)
{ {
sourcesNeedingAnUpdate.removeValue (source); const ScopedLock sl (lock);
sourcesNeedingUpdate.removeFirstMatchingValue (source);
if (sourcesBeingIterated != nullptr)
sourcesBeingIterated->removeValue (source);
} }
WeakReference<SharedValueSourceUpdater>::Master masterReference;
private: private:
typedef SortedSet<Value::ValueSource*> SourceSet; Array<Value::ValueSource*> sourcesNeedingUpdate;
SourceSet sourcesNeedingAnUpdate; CriticalSection lock;
SourceSet* sourcesBeingIterated;
void handleAsyncUpdate() override void handleAsyncUpdate() override
{ {
const ReferenceCountedObjectPtr<SharedValueSourceUpdater> localRef (this); SharedResourcePointer<SharedValueSourceUpdater> localRef;
int maxCallbacks = sourcesNeedingUpdate.size();
for (;;)
{ {
const ScopedValueSetter<SourceSet*> inside (sourcesBeingIterated, nullptr, nullptr); ReferenceCountedObjectPtr<Value::ValueSource> toUpdate;
int maxLoops = 10;
while (sourcesNeedingAnUpdate.size() > 0)
{ {
if (--maxLoops == 0) const ScopedLock sl (lock);
{ toUpdate = sourcesNeedingUpdate.remove (0);
triggerAsyncUpdate(); }
break;
}
SourceSet sources; if (toUpdate == nullptr)
sources.swapWith (sourcesNeedingAnUpdate); break;
sourcesBeingIterated = &sources;
for (int i = sources.size(); --i >= 0;) toUpdate->sendChangeMessage (true);
if (i < sources.size())
sources.getUnchecked(i)->sendChangeMessage (true); if (--maxCallbacks <= 0)
{
triggerAsyncUpdate();
break;
} }
} }
} }
@ -82,7 +78,10 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedValueSourceUpdater) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedValueSourceUpdater)
}; };
static WeakReference<SharedValueSourceUpdater> sharedUpdater; struct Value::ValueSource::Pimpl
{
SharedResourcePointer<SharedValueSourceUpdater> updater;
};
Value::ValueSource::ValueSource() Value::ValueSource::ValueSource()
{ {
@ -90,8 +89,8 @@ Value::ValueSource::ValueSource()
Value::ValueSource::~ValueSource() Value::ValueSource::~ValueSource()
{ {
if (asyncUpdater != nullptr) if (pimpl != nullptr)
static_cast <SharedValueSourceUpdater*> (asyncUpdater.get())->valueDeleted (this); pimpl->updater->valueDeleted (this);
} }
void Value::ValueSource::sendChangeMessage (const bool synchronous) void Value::ValueSource::sendChangeMessage (const bool synchronous)
@ -103,7 +102,6 @@ void Value::ValueSource::sendChangeMessage (const bool synchronous)
if (synchronous) if (synchronous)
{ {
const ReferenceCountedObjectPtr<ValueSource> localRef (this); const ReferenceCountedObjectPtr<ValueSource> localRef (this);
asyncUpdater = nullptr;
for (int i = numListeners; --i >= 0;) for (int i = numListeners; --i >= 0;)
if (Value* const v = valuesWithListeners[i]) if (Value* const v = valuesWithListeners[i])
@ -111,22 +109,10 @@ void Value::ValueSource::sendChangeMessage (const bool synchronous)
} }
else else
{ {
SharedValueSourceUpdater* updater = static_cast <SharedValueSourceUpdater*> (asyncUpdater.get()); if (pimpl == nullptr)
pimpl = new Pimpl();
if (updater == nullptr) pimpl->updater->update (this);
{
if (sharedUpdater == nullptr)
{
asyncUpdater = updater = new SharedValueSourceUpdater();
sharedUpdater = updater;
}
else
{
asyncUpdater = updater = sharedUpdater.get();
}
}
updater->update (this);
} }
} }
} }
@ -195,13 +181,13 @@ Value& Value::operator= (const Value& other)
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS #if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
Value::Value (Value&& other) noexcept Value::Value (Value&& other) noexcept
: value (static_cast <ReferenceCountedObjectPtr <ValueSource>&&> (other.value)) : value (static_cast<ReferenceCountedObjectPtr<ValueSource>&&> (other.value))
{ {
} }
Value& Value::operator= (Value&& other) noexcept Value& Value::operator= (Value&& other) noexcept
{ {
value = static_cast <ReferenceCountedObjectPtr <ValueSource>&&> (other.value); value = static_cast<ReferenceCountedObjectPtr<ValueSource>&&> (other.value);
return *this; return *this;
} }
#endif #endif

View file

@ -192,8 +192,13 @@ public:
protected: protected:
//============================================================================== //==============================================================================
friend class Value; friend class Value;
SortedSet <Value*> valuesWithListeners; SortedSet<Value*> valuesWithListeners;
ReferenceCountedObjectPtr<ReferenceCountedObject> asyncUpdater;
private:
struct Pimpl;
friend struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSource) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSource)
}; };
@ -210,8 +215,8 @@ public:
private: private:
//============================================================================== //==============================================================================
friend class ValueSource; friend class ValueSource;
ReferenceCountedObjectPtr <ValueSource> value; ReferenceCountedObjectPtr<ValueSource> value;
ListenerList <Listener> listeners; ListenerList<Listener> listeners;
void callListeners(); void callListeners();