// 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 JetBrains.Annotations; // ReSharper disable ConditionIsAlwaysTrueOrFalseAccordingToNullableAPIContract namespace PerformanceFish.Cache; #pragma warning disable CS9091 [PublicAPI] public record struct ByInt where T : notnull where TResult : new() { private static FishTable, TResult> _get = Utility.AddNew, TResult>(); [ThreadStatic] private static FishTable, TResult>? _getThreadStatic; public static FishTable, TResult> Get { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _getThreadStatic ??= Utility.AddNew, TResult>(); } public static FishTable, TResult> GetDirectly { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(int key) => ref Get.GetOrAddReference(Unsafe.As>(ref key)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(ByInt key) => ref Get.GetOrAddReference(key); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(ref ByInt key) => ref Get.GetOrAddReference(ref key); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(int key) => ref Get.GetReference(Unsafe.As>(ref key)); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(T key) => ref Get.GetReference(new(key)); public int Key; [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ByInt(T key) => Key = FunctionPointers.IndexGetter.Default(key); [MethodImpl(MethodImplOptions.AggressiveInlining)] public ByInt(int key) => Key = key; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ByInt other) => Key == other.Key; [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => Key; } [PublicAPI] public record struct ByInt where T1 : notnull where T2 : notnull where TResult : new() { private static FishTable, TResult> _get = Utility.AddNew, TResult>(); [ThreadStatic] private static FishTable, TResult>? _getThreadStatic; public static FishTable, TResult> Get { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _getThreadStatic ??= Utility.AddNew, TResult>(); } private static ref FishTable, TResult> GetCacheRef { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { _getThreadStatic ??= Utility.AddNew, TResult>(); return ref _getThreadStatic!; } } public static FishTable, TResult> GetDirectly { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(int first, int second) => ref Get.GetOrAddReference(new() { First = first, Second = second }); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(in ByInt key) => ref Get.GetOrAddReference(ref Unsafe.AsRef(in key)); // [MethodImpl(MethodImplOptions.AggressiveInlining)] // public static ref TResult GetOrAddReference(long key) // different, worse, GetHashCode method // => ref Unsafe.As, TResult>, FishTable>(ref GetCacheRef) // .GetOrAddReference(key); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(int first, int second) => ref Get.GetReference(new() { First = first, Second = second }); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(T1 first, T2 second) => ref Get.GetReference(new(first, second)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ByInt(T1 first, T2 second) { First = FunctionPointers.IndexGetter.Default(first); Second = FunctionPointers.IndexGetter.Default(second); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public ByInt(int first, int second) { First = first; Second = second; } public int First, Second; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ByInt other) => Unsafe.As, long>(ref this) == Unsafe.As, long>(ref other); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => HashCode.Combine(First, Second); } [PublicAPI] public record struct ByInt where T1 : notnull where T2 : notnull where T3 : notnull where TResult : new() { private static FishTable, TResult> _get = Utility.AddNew, TResult>(); [ThreadStatic] private static FishTable, TResult>? _getThreadStatic; public static FishTable, TResult> Get { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _getThreadStatic ??= Utility.AddNew, TResult>(); } public static FishTable, TResult> GetDirectly { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe ref TResult GetOrAddReference(int first, int second, int third) { var key = new ByInt { First = first, Second = second, Third = third }; return ref Get.GetOrAddReference(ref key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(in ByInt key) => ref Get.GetOrAddReference(ref Unsafe.AsRef(in key)); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(int first, int second, int third) => ref Get.GetReference(new() { First = first, Second = second, Third = third }); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(T1 first, T2 second, T3 third) => ref Get.GetReference(new(first, second, third)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ByInt(T1 first, T2 second, T3 third) { First = FunctionPointers.IndexGetter.Default(first); Second = FunctionPointers.IndexGetter.Default(second); Third = FunctionPointers.IndexGetter.Default(third); } public int First, Second, Third; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ByInt other) => (Unsafe.As, long>(ref this) == Unsafe.As, long>(ref other)) & (Third == other.Third); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => HashCode.Combine(First, Second, Third); } [PublicAPI] public record struct ByInt where T1 : notnull where T2 : notnull where T3 : notnull where T4 : notnull where TResult : new() { private static FishTable, TResult> _get = Utility.AddNew, TResult>(); [ThreadStatic] private static FishTable, TResult>? _getThreadStatic; public static FishTable, TResult> Get { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _getThreadStatic ??= Utility.AddNew, TResult>(); } public static FishTable, TResult> GetDirectly { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => _get; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe ref TResult GetOrAddReference(int first, int second, int third, int fourth) { var key = new ByInt { First = first, Second = second, Third = third, Fourth = fourth }; return ref Get.GetOrAddReference(ref key); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ref TResult GetOrAddReference(in ByInt key) => ref Get.GetOrAddReference(ref Unsafe.AsRef(in key)); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(int first, int second, int third, int fourth) => ref Get.GetReference(new() { First = first, Second = second, Third = third, Fourth = fourth }); [MethodImpl(MethodImplOptions.NoInlining)] public static ref TResult GetExistingReference(T1 first, T2 second, T3 third, T4 fourth) => ref Get.GetReference(new(first, second, third, fourth)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe ByInt(T1 first, T2 second, T3 third, T4 fourth) { First = FunctionPointers.IndexGetter.Default(first); Second = FunctionPointers.IndexGetter.Default(second); Third = FunctionPointers.IndexGetter.Default(third); Fourth = FunctionPointers.IndexGetter.Default(fourth); } public int First, Second, Third, Fourth; [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Equals(ByInt other) => (Unsafe.As, long>(ref this) == Unsafe.As, long>(ref other)) & (Unsafe.As(ref Third) == Unsafe.As(ref other.Third)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public override int GetHashCode() => HashCode.Combine(First, Second, Third, Fourth); } #pragma warning restore CS9091