Browse Source

Merge branch 'master' into master

pull/8026/head
Max Katz 4 years ago
committed by GitHub
parent
commit
ea7284ebc7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      src/Avalonia.Base/Utilities/WeakHashList.cs
  2. 66
      tests/Avalonia.Base.UnitTests/Utilities/WeakHashListTests.cs

13
src/Avalonia.Base/Utilities/WeakHashList.cs

@ -6,6 +6,8 @@ namespace Avalonia.Utilities;
internal class WeakHashList<T> where T : class internal class WeakHashList<T> where T : class
{ {
public const int DefaultArraySize = 8;
private struct Key private struct Key
{ {
public WeakReference<T>? Weak; public WeakReference<T>? Weak;
@ -63,7 +65,8 @@ internal class WeakHashList<T> where T : class
WeakReference<T>?[]? _arr; WeakReference<T>?[]? _arr;
int _arrCount; int _arrCount;
public bool IsEmpty => _dic == null || _dic.Count == 0; public bool IsEmpty => _dic is not null ? _dic.Count == 0 : _arrCount == 0;
public bool NeedCompact { get; private set; } public bool NeedCompact { get; private set; }
public void Add(T item) public void Add(T item)
@ -79,7 +82,7 @@ internal class WeakHashList<T> where T : class
} }
if (_arr == null) if (_arr == null)
_arr = new WeakReference<T>[8]; _arr = new WeakReference<T>[DefaultArraySize];
if (_arrCount < _arr.Length) if (_arrCount < _arr.Length)
{ {
@ -108,6 +111,7 @@ internal class WeakHashList<T> where T : class
Add(item); Add(item);
_arr = null; _arr = null;
_arrCount = 0;
} }
public void Remove(T item) public void Remove(T item)
@ -119,7 +123,7 @@ internal class WeakHashList<T> where T : class
if (_arr[c]?.TryGetTarget(out var target) == true && target == item) if (_arr[c]?.TryGetTarget(out var target) == true && target == item)
{ {
_arr[c] = null; _arr[c] = null;
Compact(); ArrCompact();
return; return;
} }
} }
@ -219,7 +223,6 @@ internal class WeakHashList<T> where T : class
} }
if (_dic != null) if (_dic != null)
{ {
foreach (var kvp in _dic) foreach (var kvp in _dic)
{ {
if (kvp.Key.Weak?.TryGetTarget(out var target) == true) if (kvp.Key.Weak?.TryGetTarget(out var target) == true)
@ -235,4 +238,4 @@ internal class WeakHashList<T> where T : class
return pooled; return pooled;
} }
} }

66
tests/Avalonia.Base.UnitTests/Utilities/WeakHashListTests.cs

@ -0,0 +1,66 @@
using Avalonia.Utilities;
using Xunit;
namespace Avalonia.Base.UnitTests.Utilities;
public class WeakHashListTests
{
[Fact]
public void Is_Empty_Works()
{
var target = new WeakHashList<string>();
Assert.True(target.IsEmpty);
target.Add("1");
Assert.False(target.IsEmpty);
target.Remove("1");
Assert.True(target.IsEmpty);
// Fill array storage.
var arrMaxSize = WeakHashList<string>.DefaultArraySize;
for (int i = 0; i < arrMaxSize; i++)
{
target.Add(i.ToString());
}
Assert.False(target.IsEmpty);
// This goes above array storage and upgrades to a dictionary.
target.Add(arrMaxSize.ToString());
Assert.False(target.IsEmpty);
// Remove everything, this should still keep an empty dictionary.
for (int i = 0; i < arrMaxSize + 1; i++)
{
target.Remove(i.ToString());
}
Assert.True(target.IsEmpty);
}
[Fact]
public void Array_Compact_After_Remove_Works()
{
var target = new WeakHashList<string>();
// Use all slots in array storage.
var arrMaxSize = WeakHashList<string>.DefaultArraySize;
for (int i = 0; i < arrMaxSize; i++)
{
target.Add(i.ToString());
}
// This should compact the array.
target.Remove("3");
// And new value should fill empty space.
target.Add("42");
}
}
Loading…
Cancel
Save