CachedValue setValue vs resetToDefault

template <typename Type>
inline void CachedValue<Type>::setValue (const Type& newValue, UndoManager* undoManagerToUse)
{
    if (cachedValue != newValue || isUsingDefault())
    {
        cachedValue = newValue;
        targetTree.setProperty (targetProperty, VariantConverter<Type>::toVar (newValue), undoManagerToUse);
    }
}

template <typename Type>
inline void CachedValue<Type>::resetToDefault (UndoManager* undoManagerToUse)
{
    targetTree.removeProperty (targetProperty, undoManagerToUse);
    forceUpdateOfCachedValue();
}

With setValue it updates the cached value and then calls all the listeners. With resetToDefault it calls all the listeners and then updates the cached value.

So, if in your listener of the tree, you access the CachedValue, you will get outdated values.

I think it should be:

template <typename Type>
inline void CachedValue<Type>::resetToDefault (UndoManager* undoManagerToUse)
{
    cachedValue = defaultValue;
    targetTree.removeProperty (targetProperty, undoManagerToUse);
}

Actually, I’m not sure this will fix my issue in general.

  1. There is no guarantee in the order listeners get called
  2. CachedValue is listening to the tree
  3. My code is listening to the tree
  4. valueTreePropertyChanged will get called in any order, either for my code or CachedValue first.

So, in general, I should never access the value of CachedValue from within valueTreePropertyChanged.

I should always do it async, correct?

Yes, or call forceUpdateOfCachedValue in your valueTreePropertyChanged callback to be sure the value is up to date.

I admit that’s fairly obtuse though. I think the way to look at it is that if you’re getting a callback from the tree, you should ask the tree what it’s value is. There’s no callback from the CachedValue so you can’t rely on its value, unless you manually force it to update.