Browse Source

Merge pull request #3015 from MarchingCube/alloc-priorityobjects

Reduce closure allocations for priority level and entry.
pull/3024/head
Dariusz Komosiński 6 years ago
committed by GitHub
parent
commit
0491a0de35
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      src/Avalonia.Base/PriorityBindingEntry.cs
  2. 49
      src/Avalonia.Base/PriorityLevel.cs

23
src/Avalonia.Base/PriorityBindingEntry.cs

@ -99,37 +99,42 @@ namespace Avalonia
void IObserver<object>.OnNext(object value)
{
void Signal()
void Signal(PriorityBindingEntry instance, object newValue)
{
var notification = value as BindingNotification;
var notification = newValue as BindingNotification;
if (notification != null)
{
if (notification.HasValue || notification.ErrorType == BindingErrorType.Error)
{
Value = notification.Value;
_owner.Changed(this);
instance.Value = notification.Value;
instance._owner.Changed(instance);
}
if (notification.ErrorType != BindingErrorType.None)
{
_owner.Error(this, notification);
instance._owner.Error(instance, notification);
}
}
else
{
Value = value;
_owner.Changed(this);
instance.Value = newValue;
instance._owner.Changed(instance);
}
}
if (Dispatcher.UIThread.CheckAccess())
{
Signal();
Signal(this, value);
}
else
{
Dispatcher.UIThread.Post(Signal);
// To avoid allocating closure in the outer scope we need to capture variables
// locally. This allows us to skip most of the allocations when on UI thread.
var instance = this;
var newValue = value;
Dispatcher.UIThread.Post(() => Signal(instance, newValue));
}
}

49
src/Avalonia.Base/PriorityLevel.cs

@ -110,20 +110,7 @@ namespace Avalonia
entry.Start(binding);
return Disposable.Create(() =>
{
if (!entry.HasCompleted)
{
Bindings.Remove(node);
entry.Dispose();
if (entry.Index >= ActiveBindingIndex)
{
ActivateFirstBinding();
}
}
});
return new RemoveBindingDisposable(node, Bindings, this);
}
/// <summary>
@ -191,5 +178,39 @@ namespace Avalonia
ActiveBindingIndex = -1;
Owner.LevelValueChanged(this);
}
private sealed class RemoveBindingDisposable : IDisposable
{
private readonly LinkedListNode<PriorityBindingEntry> _binding;
private readonly LinkedList<PriorityBindingEntry> _bindings;
private readonly PriorityLevel _priorityLevel;
public RemoveBindingDisposable(
LinkedListNode<PriorityBindingEntry> binding,
LinkedList<PriorityBindingEntry> bindings,
PriorityLevel priorityLevel)
{
_binding = binding;
_bindings = bindings;
_priorityLevel = priorityLevel;
}
public void Dispose()
{
PriorityBindingEntry entry = _binding.Value;
if (!entry.HasCompleted)
{
_bindings.Remove(_binding);
entry.Dispose();
if (entry.Index >= _priorityLevel.ActiveBindingIndex)
{
_priorityLevel.ActivateFirstBinding();
}
}
}
}
}
}

Loading…
Cancel
Save