Browse Source

Remove SetAndRaise callback handling. Move event raising to setter.

pull/2362/head
Dariusz Komosinski 7 years ago
parent
commit
812c5f30c9
  1. 82
      src/Avalonia.Base/AvaloniaObject.cs
  2. 4
      src/Avalonia.Base/Utilities/AvaloniaPropertyCollection.cs
  3. 27
      src/Avalonia.Base/Utilities/DeferredSetterOptimized.cs
  4. 14
      src/Avalonia.Base/ValueStore.cs
  5. 2
      tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj
  6. 2
      tests/Avalonia.Benchmarks/Base/DirectPropertyBenchmark.cs

82
src/Avalonia.Base/AvaloniaObject.cs

@ -466,7 +466,7 @@ namespace Avalonia
/// <param name="oldValue">The old property value.</param>
/// <param name="newValue">The new property value.</param>
/// <param name="priority">The priority of the binding that produced the value.</param>
protected void RaisePropertyChanged(
protected internal void RaisePropertyChanged(
AvaloniaProperty property,
object oldValue,
object newValue,
@ -569,44 +569,6 @@ namespace Avalonia
=> SetAndRaiseCore(property, ref backing, val, notifyWrapper),
value);
}
/// <summary>
/// Default setter handler that will set backing field and raise notification.
/// </summary>
private sealed class DefaultSetterHandler<T> : DeferredSetterOptimized<T>.ISetterHandler
{
public static readonly DefaultSetterHandler<T> Instance = new DefaultSetterHandler<T>();
public bool Update(AvaloniaObject source, AvaloniaProperty<T> property, ref T backing, T value)
{
var old = backing;
backing = value;
source.RaisePropertyChanged(property, old, value);
return true;
}
}
/// <summary>
/// Setter handler that will run custom user callback.
/// </summary>
private sealed class CallbackSetterHandler<T> : DeferredSetterOptimized<T>.ISetterHandler
{
private readonly SetAndRaiseCallback<T> _callback;
public CallbackSetterHandler(SetAndRaiseCallback<T> callback)
{
_callback = callback;
}
public bool Update(AvaloniaObject source, AvaloniaProperty<T> property, ref T backing, T value)
{
_callback(value, ref backing, notification => notification());
return true;
}
}
protected bool SetAndRaiseOptimized<T>(AvaloniaProperty<T> property, ref T field, T value)
{
@ -619,39 +581,21 @@ namespace Avalonia
DeferredSetterOptimized<T> setter = Values.GetDeferredSetter(property);
return setter.SetAndNotify(this, property, DefaultSetterHandler<T>.Instance, ref field, value);
}
protected bool SetAndRaiseOptimized<T>(
AvaloniaProperty<T> property,
ref T field,
SetAndRaiseCallback<T> setterCallback,
T value)
{
VerifyAccess();
if (EqualityComparer<T>.Default.Equals(field, value))
{
return false;
}
DeferredSetterOptimized<T> setter = Values.GetDeferredSetter(property);
return setter.SetAndNotify(this, property, new CallbackSetterHandler<T>(setterCallback) , ref field, value);
return setter.SetAndNotify(this, property, ref field, value);
}
/// <summary>
/// Default assignment logic for SetAndRaise.
/// </summary>
/// <typeparam name="T">The type of the property.</typeparam>
/// <param name="property">The property.</param>
/// <param name="field">The backing field.</param>
/// <param name="value">The value.</param>
/// <param name="notifyWrapper">A wrapper for the property-changed notification.</param>
/// <returns>
/// True if the value changed, otherwise false.
/// </returns>
private bool SetAndRaiseCore<T>(AvaloniaProperty property, ref T field, T value, Action<Action> notifyWrapper)
/// Default assignment logic for SetAndRaise.
/// </summary>
/// <typeparam name="T">The type of the property.</typeparam>
/// <param name="property">The property.</param>
/// <param name="field">The backing field.</param>
/// <param name="value">The value.</param>
/// <param name="notifyWrapper">A wrapper for the property-changed notification.</param>
/// <returns>
/// True if the value changed, otherwise false.
/// </returns>
private bool SetAndRaiseCore<T>(AvaloniaProperty property, ref T field, T value, Action<Action> notifyWrapper)
{
var old = field;
field = value;

4
src/Avalonia.Base/Utilities/AvaloniaPropertyCollection.cs

@ -95,7 +95,7 @@ namespace Avalonia.Utilities
return true;
}
public void AddValueInternal(AvaloniaProperty property, TValue value)
public void AddValue(AvaloniaProperty property, TValue value)
{
Entry[] entries = new Entry[_entries.Length + 1];
@ -117,7 +117,7 @@ namespace Avalonia.Utilities
_entries = entries;
}
public void SetValueInternal(AvaloniaProperty property, TValue value)
public void SetValue(AvaloniaProperty property, TValue value)
{
_entries[TryFindEntry(property.Id).Item1].Value = value;
}

27
src/Avalonia.Base/Utilities/DeferredSetterOptimized.cs

@ -17,20 +17,26 @@ namespace Avalonia.Utilities
_pendingValues = new SingleOrQueue<TSetRecord>();
}
private static void SetAndRaisePropertyChanged(AvaloniaObject source, AvaloniaProperty<TSetRecord> property, ref TSetRecord backing, TSetRecord value)
{
var old = backing;
backing = value;
source.RaisePropertyChanged(property, old, value);
}
public bool SetAndNotify(
AvaloniaObject source,
AvaloniaProperty<TSetRecord> property,
ISetterHandler handler,
ref TSetRecord backing,
TSetRecord value)
{
if (!_isNotifying)
{
bool updated;
using (new NotifyDisposable(this))
{
updated = handler.Update(source, property, ref backing, value);
SetAndRaisePropertyChanged(source, property, ref backing, value);
}
if (!_pendingValues.Empty)
@ -39,12 +45,12 @@ namespace Avalonia.Utilities
{
while (!_pendingValues.Empty)
{
updated = handler.Update(source, property, ref backing, _pendingValues.Dequeue());
SetAndRaisePropertyChanged(source, property, ref backing, _pendingValues.Dequeue());
}
}
}
return updated;
return true;
}
_pendingValues.Enqueue(value);
@ -71,14 +77,5 @@ namespace Avalonia.Utilities
_setter._isNotifying = false;
}
}
public interface ISetterHandler
{
bool Update(
AvaloniaObject source,
AvaloniaProperty<TSetRecord> property,
ref TSetRecord backing,
TSetRecord value);
}
}
}

14
src/Avalonia.Base/ValueStore.cs

@ -33,13 +33,13 @@ namespace Avalonia
{
priorityValue = CreatePriorityValue(property);
priorityValue.SetValue(v, (int)BindingPriority.LocalValue);
_propertyValues.SetValueInternal(property, priorityValue);
_propertyValues.SetValue(property, priorityValue);
}
}
else
{
priorityValue = CreatePriorityValue(property);
_propertyValues.AddValueInternal(property, priorityValue);
_propertyValues.AddValue(property, priorityValue);
}
return priorityValue.Add(source, (int)priority);
@ -57,7 +57,7 @@ namespace Avalonia
{
if (priority == (int)BindingPriority.LocalValue)
{
_propertyValues.SetValueInternal(property, Validate(property, value));
_propertyValues.SetValue(property, Validate(property, value));
Changed(property, priority, v, value);
return;
}
@ -65,7 +65,7 @@ namespace Avalonia
{
priorityValue = CreatePriorityValue(property);
priorityValue.SetValue(v, (int)BindingPriority.LocalValue);
_propertyValues.SetValueInternal(property, priorityValue);
_propertyValues.SetValue(property, priorityValue);
}
}
}
@ -78,14 +78,14 @@ namespace Avalonia
if (priority == (int)BindingPriority.LocalValue)
{
_propertyValues.AddValueInternal(property, Validate(property, value));
_propertyValues.AddValue(property, Validate(property, value));
Changed(property, priority, AvaloniaProperty.UnsetValue, value);
return;
}
else
{
priorityValue = CreatePriorityValue(property);
_propertyValues.AddValueInternal(property, priorityValue);
_propertyValues.AddValue(property, priorityValue);
}
}
@ -187,7 +187,7 @@ namespace Avalonia
var newDeferredSetter = new DeferredSetterOptimized<T>();
_deferredSetters.AddValueInternal(property, newDeferredSetter);
_deferredSetters.AddValue(property, newDeferredSetter);
return newDeferredSetter;
}

2
tests/Avalonia.Benchmarks/Avalonia.Benchmarks.csproj

@ -18,7 +18,7 @@
<ProjectReference Include="..\Avalonia.UnitTests\Avalonia.UnitTests.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.10.14" />
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" />
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\" />

2
tests/Avalonia.Benchmarks/Base/DirectPropertyBenchmark.cs

@ -79,4 +79,4 @@ namespace Avalonia.Benchmarks.Base
}
}
}
}
}

Loading…
Cancel
Save