Browse Source

Fix for subtle race condition in Value.

tags/2021-05-28
jules 11 years ago
parent
commit
824faca68b
2 changed files with 12 additions and 72 deletions
  1. +9
    -67
      modules/juce_data_structures/values/juce_Value.cpp
  2. +3
    -5
      modules/juce_data_structures/values/juce_Value.h

+ 9
- 67
modules/juce_data_structures/values/juce_Value.cpp View File

@@ -22,75 +22,18 @@
==============================================================================
*/
struct SharedValueSourceUpdater : private AsyncUpdater
{
public:
SharedValueSourceUpdater() {}
void update (Value::ValueSource* const source)
{
{
const ScopedLock sl (lock);
sourcesNeedingUpdate.addIfNotAlreadyThere (source);
}
triggerAsyncUpdate();
}
void valueDeleted (Value::ValueSource* const source)
{
const ScopedLock sl (lock);
sourcesNeedingUpdate.removeFirstMatchingValue (source);
}
private:
Array<Value::ValueSource*> sourcesNeedingUpdate;
CriticalSection lock;
void handleAsyncUpdate() override
{
SharedResourcePointer<SharedValueSourceUpdater> localRef;
int maxCallbacks = sourcesNeedingUpdate.size();
for (;;)
{
ReferenceCountedObjectPtr<Value::ValueSource> toUpdate;
{
const ScopedLock sl (lock);
toUpdate = sourcesNeedingUpdate.remove (0);
}
if (toUpdate == nullptr)
break;
toUpdate->sendChangeMessage (true);
if (--maxCallbacks <= 0)
{
triggerAsyncUpdate();
break;
}
}
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SharedValueSourceUpdater)
};
struct Value::ValueSource::Pimpl
{
SharedResourcePointer<SharedValueSourceUpdater> updater;
};
Value::ValueSource::ValueSource()
{
}
Value::ValueSource::~ValueSource()
{
if (pimpl != nullptr)
pimpl->updater->valueDeleted (this);
cancelPendingUpdate();
}
void Value::ValueSource::handleAsyncUpdate()
{
sendChangeMessage (true);
}
void Value::ValueSource::sendChangeMessage (const bool synchronous)
@@ -103,16 +46,15 @@ void Value::ValueSource::sendChangeMessage (const bool synchronous)
{
const ReferenceCountedObjectPtr<ValueSource> localRef (this);
cancelPendingUpdate();
for (int i = numListeners; --i >= 0;)
if (Value* const v = valuesWithListeners[i])
v->callListeners();
}
else
{
if (pimpl == nullptr)
pimpl = new Pimpl();
pimpl->updater->update (this);
triggerAsyncUpdate();
}
}
}


+ 3
- 5
modules/juce_data_structures/values/juce_Value.h View File

@@ -167,7 +167,8 @@ public:
of a ValueSource object. If you're feeling adventurous, you can create your own custom
ValueSource classes to allow Value objects to represent your own custom data items.
*/
class JUCE_API ValueSource : public SingleThreadedReferenceCountedObject
class JUCE_API ValueSource : public ReferenceCountedObject,
private AsyncUpdater
{
public:
ValueSource();
@@ -195,10 +196,7 @@ public:
SortedSet<Value*> valuesWithListeners;
private:
struct Pimpl;
friend struct Pimpl;
friend struct ContainerDeletePolicy<Pimpl>;
ScopedPointer<Pimpl> pimpl;
void handleAsyncUpdate() override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ValueSource)
};


Loading…
Cancel
Save