more default value related fixes for FishSet and FishTable

This commit is contained in:
bbradson
2024-04-15 07:27:58 +02:00
parent 040a756d2e
commit 5656c3e80b
12 changed files with 58 additions and 23 deletions
+17 -10
View File
@@ -636,24 +636,31 @@ public static class CollectionExtensions
return destination;
}
public static unsafe void Fill<T>(this T[] array, T value)
public static void Fill<T>(this T[] array, T value)
{
Guard.IsNotNull(array);
var i = array.Length - 1;
if (array.Length == 0)
if (i < 0)
return;
fixed (T* startAddress = &array[0])
do
{
var i = array.Length - 1;
do
{
startAddress[i] = value;
}
while (--i >= 0);
array.UnsafeStore(i, value);
}
while (--i >= 0);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static T UnsafeLoad<T>(this T[] array, int index) => Array.UnsafeLoad(array, index);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void UnsafeStore<T>(this T[] array, int index, T value) => Array.UnsafeStore(array, index, value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static TTo UnsafeCast<TFrom, TTo>(this TFrom obj) => Array.UnsafeMov<TFrom, TTo>(obj);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void AddRangeFast<T>(this List<T> list, T[] range)
{
+21 -7
View File
@@ -205,7 +205,11 @@ public class FishSet<T> : ISet<T>, IReadOnlyCollection<T>, ICollection
private void SetBucketEmpty(int index)
{
_buckets[index] = _defaultValue;
var buckets = _buckets;
if (buckets.Length <= index)
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
buckets.UnsafeStore(index, _defaultValue);
_tails.SetEmpty(index);
}
@@ -303,10 +307,10 @@ public class FishSet<T> : ISet<T>, IReadOnlyCollection<T>, ICollection
return tailCount;
}
private bool IsBucketEmpty(int bucketIndex) => IsBucketEmpty(bucketIndex, _tails, _buckets);
private bool IsBucketEmpty(int bucketIndex) => IsBucketEmpty(bucketIndex, _tails);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool IsBucketEmpty(int bucketIndex, Tails tails, T?[] buckets) => tails.IsEmpty(bucketIndex);
private static bool IsBucketEmpty(int bucketIndex, Tails tails) => tails.IsEmpty(bucketIndex);
private bool TryFindTailIndexAndReplace(T entry, ref int bucketIndex, ReplaceBehaviour replaceBehaviour)
{
@@ -389,12 +393,15 @@ public class FishSet<T> : ISet<T>, IReadOnlyCollection<T>, ICollection
var tailingEntries = new PooledIList<List<T>>();
var tailingEntriesList = tailingEntries.List;
var tailIndex = GetTailIndex(bucketIndex);
var buckets = _buckets;
while (true)
{
ref var tailingBucket = ref _buckets[tailIndex];
tailingEntriesList.Add(tailingBucket!);
tailingBucket = _defaultValue;
if (tailIndex >= buckets.Length)
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
tailingEntriesList.Add(buckets.UnsafeLoad(tailIndex)!);
buckets.UnsafeStore(tailIndex, _defaultValue);
if (HasTail(tailIndex))
{
@@ -454,7 +461,7 @@ public class FishSet<T> : ISet<T>, IReadOnlyCollection<T>, ICollection
for (var i = 0; i < oldBuckets.Length; i++)
{
if (!IsBucketEmpty(i, oldTails, oldBuckets))
if (!IsBucketEmpty(i, oldTails))
InsertEntry(oldBuckets[i]!, ReplaceBehaviour.Throw, true);
}
}
@@ -802,6 +809,13 @@ public class FishSet<T> : ISet<T>, IReadOnlyCollection<T>, ICollection
internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
=> throw new InvalidOperationException("Enumeration has either not started or has already finished.");
[DoesNotReturn]
internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
=> throw new InvalidOperationException(
"Operations that change non-concurrent collections must have exclusive access. A concurrent "
+ "update was performed on this collection and corrupted its state. The collection's state is no "
+ "longer correct.");
[DoesNotReturn]
internal static void ThrowWrongKeyTypeArgumentException(object? key)
{
+18 -4
View File
@@ -312,7 +312,11 @@ public class FishTable<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, I
private void SetBucketEmpty(int index)
{
_buckets[index] = _defaultEntry;
var buckets = _buckets;
if (buckets.Length <= index)
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
buckets.UnsafeStore(index, _defaultEntry);
_tails.SetEmpty(index);
}
@@ -565,12 +569,15 @@ public class FishTable<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, I
var tailingEntries = new PooledIList<List<Entry>>();
var tailingEntriesList = tailingEntries.List;
var tailIndex = GetTailIndex(bucketIndex);
var buckets = _buckets;
while (true)
{
ref var tailingBucket = ref _buckets[tailIndex];
tailingEntriesList.Add(tailingBucket);
tailingBucket = _defaultEntry;
if (tailIndex >= buckets.Length)
ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported();
tailingEntriesList.Add(buckets.UnsafeLoad(tailIndex));
buckets.UnsafeStore(tailIndex, _defaultEntry);
if (HasTail(tailIndex))
{
@@ -1759,6 +1766,13 @@ public class FishTable<TKey, TValue> : IDictionary<TKey, TValue>, IDictionary, I
internal static void ThrowInvalidOperationException_InvalidOperation_EnumOpCantHappen()
=> throw new InvalidOperationException("Enumeration has either not started or has already finished.");
[DoesNotReturn]
internal static void ThrowInvalidOperationException_ConcurrentOperationsNotSupported()
=> throw new InvalidOperationException(
"Operations that change non-concurrent collections must have exclusive access. A concurrent "
+ "update was performed on this collection and corrupted its state. The collection's state is no "
+ "longer correct.");
[DoesNotReturn]
internal static void ThrowKeyNotFoundException<T>(T key)
{
+2 -2
View File
@@ -29,11 +29,11 @@ namespace FisheryLib;
[PublicAPI]
public static class FisheryLib
{
public const decimal VERSION = 0.511M;
public const decimal VERSION = 0.512M;
public static decimal CurrentlyLoadedVersion { get; } = VERSION;
public const string VERSION_STRING = "0.5.1.1";
public const string VERSION_STRING = "0.5.1.2";
// public static string GetVersion()
// {