Browse Source

Use LocalValueEntry instead of boxing.

Further reduces allocated memory in the common case of only a local value being set.
pull/3287/head
Steven Kirk 7 years ago
parent
commit
44e1bd5158
  1. 19
      src/Avalonia.Base/PropertyStore/LocalValueEntry.cs
  2. 42
      src/Avalonia.Base/ValueStore.cs

19
src/Avalonia.Base/PropertyStore/LocalValueEntry.cs

@ -0,0 +1,19 @@
using Avalonia.Data;
#nullable enable
namespace Avalonia.PropertyStore
{
internal class LocalValueEntry<T> : IValue<T>
{
public LocalValueEntry(T value) => Value = value;
public Optional<T> Value { get; set; }
public BindingPriority ValuePriority => BindingPriority.LocalValue;
Optional<object> IValue.Value => Value.ToObject();
public ConstantValueEntry<T> ToConstantValueEntry(StyledPropertyBase<T> property)
{
return new ConstantValueEntry<T>(property, Value.Value, BindingPriority.LocalValue);
}
}
}

42
src/Avalonia.Base/ValueStore.cs

@ -41,10 +41,6 @@ namespace Avalonia
{ {
return v.Value.HasValue; return v.Value.HasValue;
} }
else
{
return true;
}
} }
return false; return false;
@ -62,11 +58,6 @@ namespace Avalonia
return true; return true;
} }
} }
else
{
value = (T)slot;
return true;
}
} }
value = default!; value = default!;
@ -81,7 +72,7 @@ namespace Avalonia
} }
else if (priority == BindingPriority.LocalValue) else if (priority == BindingPriority.LocalValue)
{ {
_values.AddValue(property, (object)value!); _values.AddValue(property, new LocalValueEntry<T>(value));
_sink.ValueChanged(property, priority, default, value); _sink.ValueChanged(property, priority, default, value);
} }
else else
@ -174,18 +165,25 @@ namespace Avalonia
{ {
p.SetValue(value, priority); p.SetValue(value, priority);
} }
else if (priority == BindingPriority.LocalValue) else if (slot is LocalValueEntry<T> l)
{ {
var old = (T)slot; if (priority == BindingPriority.LocalValue)
_values.SetValue(property, (object)value!); {
_sink.ValueChanged(property, priority, old, value); var old = l.Value;
l.Value = value;
_sink.ValueChanged(property, priority, old, value);
}
else
{
var existing = l.ToConstantValueEntry(property);
var priorityValue = new PriorityValue<T>(_owner, property, this, existing);
priorityValue.SetValue(value, priority);
_values.SetValue(property, priorityValue);
}
} }
else else
{ {
var existing = new ConstantValueEntry<T>(property, (T)slot, BindingPriority.LocalValue); throw new NotSupportedException("Unrecognised value store slot type.");
var priorityValue = new PriorityValue<T>(_owner, property, this, existing);
priorityValue.SetValue(value, priority);
_values.SetValue(property, priorityValue);
} }
} }
@ -205,11 +203,15 @@ namespace Avalonia
{ {
priorityValue = p; priorityValue = p;
} }
else else if (slot is LocalValueEntry<T> l)
{ {
var existing = new ConstantValueEntry<T>(property, (T)slot, BindingPriority.LocalValue); var existing = l.ToConstantValueEntry(property);
priorityValue = new PriorityValue<T>(_owner, property, this, existing); priorityValue = new PriorityValue<T>(_owner, property, this, existing);
} }
else
{
throw new NotSupportedException("Unrecognised value store slot type.");
}
var binding = priorityValue.AddBinding(source, priority); var binding = priorityValue.AddBinding(source, priority);
_values.SetValue(property, priorityValue); _values.SetValue(property, priorityValue);

Loading…
Cancel
Save