Added pools, IndexedFishMap, IndexedFishSet, fixed bugs related to FishTable.Remove, added Preview.png, various smaller additions, some refactoring too

This commit is contained in:
bbradson
2024-01-27 10:02:57 +01:00
parent cdf209eb02
commit af759661bd
38 changed files with 1879 additions and 642 deletions
+37
View File
@@ -0,0 +1,37 @@
// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Runtime.CompilerServices;
namespace FisheryLib.Pools;
public static class FishPool<T> where T : IFishPoolable
{
private static T?[] _freeItems = new T[4];
private static int _freeItemCount;
public static T Get()
{
if (_freeItemCount == 0)
return Reflection.New<T>();
var freeItem = _freeItems[--_freeItemCount];
_freeItems[_freeItemCount] = default;
return freeItem!;
}
public static void Return(T item)
{
item.Reset();
if (++_freeItemCount >= _freeItems.Length)
ExpandFreeItems();
_freeItems[_freeItemCount - 1] = item;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ExpandFreeItems() => Array.Resize(ref _freeItems, _freeItems.Length << 1);
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright (c) 2022 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v.2.0.If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
namespace FisheryLib.Pools;
public interface IFishPoolable
{
public void Reset();
}
+49
View File
@@ -0,0 +1,49 @@
// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Collections;
using System.Runtime.CompilerServices;
namespace FisheryLib.Pools;
public record struct PooledIList<T>() : IDisposable where T : IList, new()
{
public T List = Get();
private static T?[] _freeItems = new T[4];
private static int _freeItemCount;
public void Dispose()
{
if (List == null)
return;
Return(List);
List = default!;
}
public static T Get()
{
if (_freeItemCount == 0)
return Reflection.New<T>();
var freeItem = _freeItems[--_freeItemCount];
_freeItems[_freeItemCount] = default;
return freeItem!;
}
public static void Return(T item)
{
item.Clear();
if (++_freeItemCount >= _freeItems.Length)
ExpandFreeItems();
_freeItems[_freeItemCount - 1] = item;
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void ExpandFreeItems() => Array.Resize(ref _freeItems, _freeItems.Length << 1);
}
@@ -0,0 +1,62 @@
// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Security;
using System.Text;
using JetBrains.Annotations;
namespace FisheryLib.Pools;
public record struct PooledStringBuilder : IDisposable
{
private FishPoolable _fishPoolable;
public StringBuilder Builder => _fishPoolable.Builder;
public StringBuilder Append(string? value) => Builder.Append(value);
public StringBuilder Append(char value) => Builder.Append(value);
public StringBuilder Append(char[] value) => Builder.Append(value);
public StringBuilder Append(PooledStringBuilderHandler value) => value.AppendToStringBuilder(Builder);
public StringBuilder AppendLine(string? value) => Builder.AppendLine(value);
public StringBuilder Insert(int index, string? value) => Builder.Insert(index, value);
public StringBuilder Insert(int index, char value) => Builder.Insert(index, value);
public StringBuilder Remove(int startIndex, int length) => Builder.Remove(startIndex, length);
public void Clear() => Builder.Clear();
public override string ToString() => Builder.ToString();
[SecuritySafeCritical]
public PooledStringBuilder() => _fishPoolable = FishPool<FishPoolable>.Get();
public PooledStringBuilder(int minimumSize) : this()
{
if (_fishPoolable.Builder.Capacity < minimumSize)
_fishPoolable.Builder.Capacity = minimumSize;
}
[SecuritySafeCritical]
public void Dispose()
{
if (_fishPoolable.Builder == null!)
return;
FishPool<FishPoolable>.Return(_fishPoolable);
_fishPoolable.Builder = null!;
}
private struct FishPoolable : IFishPoolable
{
public StringBuilder Builder = new();
public void Reset() => Builder.Clear();
[UsedImplicitly]
public FishPoolable() {}
}
}
@@ -0,0 +1,40 @@
// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Runtime.CompilerServices;
using System.Text;
using JetBrains.Annotations;
namespace FisheryLib.Pools;
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]
[InterpolatedStringHandler]
public record struct PooledStringBuilderHandler : IDisposable
{
private PooledIList<List<char>> _chars;
public PooledStringBuilderHandler(int literalLength, int formattedCount)
{
_chars = new();
_chars.List.EnsureCapacity(literalLength + (formattedCount * 8));
}
public void AppendLiteral(string s) => _chars.List.Add(s);
public void AppendFormatted<T>(T t)
{
if (t != null)
_chars.List.Add(t.ToString());
}
public StringBuilder AppendToStringBuilder(StringBuilder destination)
{
destination.Append(_chars.List);
Dispose();
return destination;
}
public void Dispose() => _chars.Dispose();
}
@@ -0,0 +1,38 @@
// Copyright (c) 2023 bradson
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
using System.Runtime.CompilerServices;
using JetBrains.Annotations;
namespace FisheryLib.Pools;
[UsedImplicitly(ImplicitUseTargetFlags.WithMembers)]
[InterpolatedStringHandler]
public record struct PooledStringHandler : IDisposable
{
private PooledStringBuilder _builder;
public PooledStringHandler(int literalLength, int formattedCount)
=> _builder = new(literalLength + (formattedCount * 8));
public void AppendLiteral(string s) => _builder.Append(s);
public void AppendFormatted<T>(T t)
{
if (typeof(T) == typeof(PooledStringBuilderHandler))
_builder.Append(Unsafe.As<T, PooledStringBuilderHandler>(ref t));
else
_builder.Append(t?.ToString());
}
public string GetFormattedText()
{
var result = _builder.ToString();
Dispose();
return result;
}
public void Dispose() => _builder.Dispose();
}