Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/Neo.Extensions/Collections/HashSetExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
// Redistribution and use in source and binary forms with or without
// modifications are permitted.

using System;
using System.Collections.Generic;

namespace Neo.Extensions
Expand All @@ -23,7 +24,20 @@ public static void Remove<T>(this HashSet<T> set, ISet<T> other)
}
else
{
set.RemoveWhere(u => other.Contains(u));
set.RemoveWhere(other.Contains);
}
}

public static void Remove<T>(this HashSet<T> set, ICollection<T> other)
where T : IEquatable<T>
{
if (set.Count > other.Count)
{
set.ExceptWith(other);
}
else
{
set.RemoveWhere(other.Contains);
}
}

Expand All @@ -35,7 +49,7 @@ public static void Remove<T, V>(this HashSet<T> set, IReadOnlyDictionary<T, V> o
}
else
{
set.RemoveWhere(u => other.ContainsKey(u));
set.RemoveWhere(other.ContainsKey);
}
}
}
Expand Down
32 changes: 31 additions & 1 deletion src/Neo.IO/Caching/HashSetCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Neo.IO.Caching
/// A cache that uses a hash set to store items.
/// </summary>
/// <typeparam name="T">The type of the items in the cache.</typeparam>
internal class HashSetCache<T> : IReadOnlyCollection<T> where T : IEquatable<T>
internal class HashSetCache<T> : ICollection<T> where T : IEquatable<T>
{
private class Items(int initialCapacity) : KeyedCollectionSlim<T, T>(initialCapacity)
{
Expand All @@ -37,6 +37,8 @@ private class Items(int initialCapacity) : KeyedCollectionSlim<T, T>(initialCapa
/// </summary>
public int Count => _items.Count;

public bool IsReadOnly => false;

/// <summary>
/// Initializes a new instance of the <see cref="HashSetCache{T}"/> class.
/// </summary>
Expand Down Expand Up @@ -103,6 +105,34 @@ public void ExceptWith(IEnumerable<T> items)
/// </summary>
/// <returns>An enumerator that can be used to iterate through the cache.</returns>
IEnumerator IEnumerable.GetEnumerator() => _items.GetEnumerator();

public void Add(T item)
{
_ = TryAdd(item);
}

public bool Remove(T item)
{
return _items.Remove(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
if (array == null)
throw new ArgumentNullException(nameof(array));

if (arrayIndex < 0 || arrayIndex > array.Length)
throw new ArgumentOutOfRangeException(nameof(arrayIndex));

if (array.Length - arrayIndex < Count)
throw new ArgumentException("The number of elements in the source ICollection<T> is greater than the available space from arrayIndex to the end of the destination array.");

var i = arrayIndex;
foreach (var item in this)
{
array[i++] = item;
}
}
}
}

Expand Down
36 changes: 0 additions & 36 deletions src/Neo/Extensions/HashSetExtensions.cs

This file was deleted.

4 changes: 2 additions & 2 deletions src/Neo/Network/P2P/TaskManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void OnNewTasks(InvPayload payload)
return;
}

HashSet<UInt256> hashes = new(payload.Hashes);
HashSet<UInt256> hashes = [.. payload.Hashes];
// Remove all previously processed knownHashes from the list that is being requested
hashes.Remove(_knownHashes);
// Add to AvailableTasks the ones, of type InventoryType.Block, that are global (already under process by other sessions)
Expand Down Expand Up @@ -372,7 +372,7 @@ private void RequestTasks(IActorRef remoteNode, TaskSession session)
session.AvailableTasks.Remove(_knownHashes);
// Search any similar hash that is on Singleton's knowledge, which means, on the way or already processed
session.AvailableTasks.RemoveWhere(p => NativeContract.Ledger.ContainsBlock(snapshot, p));
HashSet<UInt256> hashes = new(session.AvailableTasks);
HashSet<UInt256> hashes = [.. session.AvailableTasks];
if (hashes.Count > 0)
{
hashes.RemoveWhere(p => !IncrementGlobalTask(p));
Expand Down
27 changes: 23 additions & 4 deletions tests/Neo.UnitTests/IO/Caching/UT_HashSetCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,30 @@ public void TestAdd()
var b = new UInt256(key2);

var set = new HashSetCache<UInt256>(1);
set.TryAdd(a);
set.TryAdd(b);
Assert.IsTrue(set.TryAdd(a));
Assert.IsTrue(set.TryAdd(b));
CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { b });
}

[TestMethod]
public void TestCopyTo()
{
var key1 = Enumerable.Repeat((byte)1, 32).ToArray();
var a = new UInt256(key1);

var key2 = Enumerable.Repeat((byte)1, 31).Append((byte)2).ToArray();
var b = new UInt256(key2);

var set = new HashSetCache<UInt256>(1);
Assert.IsTrue(set.TryAdd(a));
Assert.IsTrue(set.TryAdd(b));

var array = new UInt256[1];
set.CopyTo(array, 0);

CollectionAssert.AreEqual(array, new UInt256[] { b });
}

[TestMethod]
public void TestGetEnumerator()
{
Expand All @@ -91,7 +110,7 @@ public void TestGetEnumerator()

var set = new HashSetCache<UInt256>(1);
set.TryAdd(a);
set.TryAdd(b);
set.Add(b);
IEnumerable ie = set;
Assert.IsNotNull(ie.GetEnumerator());
}
Expand All @@ -115,7 +134,7 @@ public void TestExceptWith()
set.ExceptWith([b, c]);
CollectionAssert.AreEqual(set.ToArray(), new UInt256[] { a });

set.ExceptWith([a]);
set.Remove(a);
CollectionAssert.AreEqual(set.ToArray(), Array.Empty<UInt256>());

set = new HashSetCache<UInt256>(10);
Expand Down
Loading