Browse Source

Merge pull request #721 from jkoritzinsky/PriorityValueOptimization

PriorityValue and PriorityLevel Memory Usage Optimization
pull/722/head
Steven Kirk 10 years ago
committed by GitHub
parent
commit
9a696dc0c3
  1. 1
      src/Avalonia.Base/Avalonia.Base.csproj
  2. 2
      src/Avalonia.Base/PriorityValue.cs
  3. 144
      src/Avalonia.Base/Utilities/SingleOrDictionary.cs

1
src/Avalonia.Base/Avalonia.Base.csproj

@ -118,6 +118,7 @@
<Compile Include="Utilities\ExceptionUtilities.cs" />
<Compile Include="Utilities\IWeakSubscriber.cs" />
<Compile Include="Utilities\MathUtilities.cs" />
<Compile Include="Utilities\SingleOrDictionary.cs" />
<Compile Include="Utilities\TypeUtilities.cs" />
<Compile Include="Utilities\WeakObservable.cs" />
<Compile Include="Utilities\WeakSubscriptionManager.cs" />

2
src/Avalonia.Base/PriorityValue.cs

@ -28,7 +28,7 @@ namespace Avalonia
{
private readonly IPriorityValueOwner _owner;
private readonly Type _valueType;
private readonly Dictionary<int, PriorityLevel> _levels = new Dictionary<int, PriorityLevel>();
private readonly SingleOrDictionary<int, PriorityLevel> _levels = new SingleOrDictionary<int, PriorityLevel>();
private object _value;
private readonly Func<object, object> _validate;

144
src/Avalonia.Base/Utilities/SingleOrDictionary.cs

@ -0,0 +1,144 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Utilities
{
/// <summary>
/// Stores either a single key value pair or constructs a dictionary when more than one value is stored.
/// </summary>
/// <typeparam name="TKey">The type of the key.</typeparam>
/// <typeparam name="TValue">The type of the value.</typeparam>
public class SingleOrDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
{
private KeyValuePair<TKey, TValue>? _singleValue;
private Dictionary<TKey, TValue> dictionary;
public void Add(TKey key, TValue value)
{
if (_singleValue != null)
{
dictionary = new Dictionary<TKey, TValue>();
((ICollection<KeyValuePair<TKey, TValue>>)dictionary).Add(_singleValue.Value);
_singleValue = null;
}
if (dictionary != null)
{
dictionary.Add(key, value);
}
else
{
_singleValue = new KeyValuePair<TKey, TValue>(key, value);
}
}
public bool TryGetValue(TKey key, out TValue value)
{
if (dictionary == null)
{
if (!_singleValue.HasValue || !_singleValue.Value.Key.Equals(key))
{
value = default(TValue);
return false;
}
else
{
value = _singleValue.Value.Value;
return true;
}
}
else
{
return dictionary.TryGetValue(key, out value);
}
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
if (dictionary == null)
{
if (_singleValue.HasValue)
{
return new SingleEnumerator<KeyValuePair<TKey, TValue>>(_singleValue.Value);
}
}
else
{
return dictionary.GetEnumerator();
}
return Enumerable.Empty<KeyValuePair<TKey, TValue>>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public IEnumerable<TValue> Values
{
get
{
if(dictionary == null)
{
if (_singleValue.HasValue)
{
return new[] { _singleValue.Value.Value };
}
}
else
{
return dictionary.Values;
}
return Enumerable.Empty<TValue>();
}
}
private class SingleEnumerator<T> : IEnumerator<T>
{
private T value;
private int index = -1;
public SingleEnumerator(T value)
{
this.value = value;
}
public T Current
{
get
{
if (index == 0)
{
return value;
}
else
{
throw new InvalidOperationException();
}
}
}
object IEnumerator.Current => Current;
public void Dispose()
{
}
public bool MoveNext()
{
index++;
return index < 1;
}
public void Reset()
{
index = -1;
}
}
}
}
Loading…
Cancel
Save