surpressed all style warnings from the LSP server.
This commit is contained in:
parent
7ee2238248
commit
23c4ac299e
13 changed files with 346 additions and 371 deletions
|
|
@ -33,17 +33,17 @@ public struct NodeHeader
|
|||
}
|
||||
|
||||
[InlineArray(32)]
|
||||
public struct KeyBuffer<K>
|
||||
public struct KeyBuffer<TK>
|
||||
{
|
||||
private K _element0;
|
||||
private TK _element0;
|
||||
}
|
||||
|
||||
// Constraint: Internal Nodes fixed at 32 children.
|
||||
// This removes the need for a separate array allocation for children references.
|
||||
[InlineArray(32)]
|
||||
public struct NodeBuffer<V>
|
||||
public struct NodeBuffer<TV>
|
||||
{
|
||||
private Node<V>? _element0;
|
||||
private Node<TV>? _element0;
|
||||
}
|
||||
|
||||
[InlineArray(32)]
|
||||
|
|
@ -52,7 +52,7 @@ internal struct InternalPrefixBuffer
|
|||
private long _element0;
|
||||
}
|
||||
|
||||
public abstract class Node<K>
|
||||
public abstract class Node<TK>
|
||||
{
|
||||
public NodeHeader Header;
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ public abstract class Node<K>
|
|||
Header = new NodeHeader(owner, 0, flags);
|
||||
}
|
||||
|
||||
public abstract Span<K> GetKeys();
|
||||
public abstract Span<TK> GetKeys();
|
||||
|
||||
// Abstract access to prefixes regardless of storage backing
|
||||
public abstract Span<long> AllPrefixes { get; }
|
||||
|
|
@ -71,47 +71,47 @@ public abstract class Node<K>
|
|||
|
||||
public bool IsLeaf => (Header.Flags & NodeFlags.IsLeaf) != 0;
|
||||
|
||||
public abstract Node<K> EnsureEditable(OwnerId transactionId);
|
||||
public abstract Node<TK> EnsureEditable(OwnerId transactionId);
|
||||
|
||||
public void SetCount(int newCount) => Header.Count = (byte)newCount;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public LeafNode<K, V> AsLeaf<V>()
|
||||
public LeafNode<TK, TV> AsLeaf<TV>()
|
||||
{
|
||||
// Zero-overhead cast. Assumes you checked IsLeaf or know logic flow.
|
||||
return Unsafe.As<LeafNode<K, V>>(this);
|
||||
return Unsafe.As<LeafNode<TK, TV>>(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public InternalNode<K> AsInternal()
|
||||
public InternalNode<TK> AsInternal()
|
||||
{
|
||||
// Zero-overhead cast. Assumes you checked !IsLeaf or know logic flow.
|
||||
return Unsafe.As<InternalNode<K>>(this);
|
||||
return Unsafe.As<InternalNode<TK>>(this);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public PrefixInternalNode<K> AsPrefixInternal()
|
||||
public PrefixInternalNode<TK> AsPrefixInternal()
|
||||
{
|
||||
return Unsafe.As<PrefixInternalNode<K>>(this);
|
||||
return Unsafe.As<PrefixInternalNode<TK>>(this);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class LeafNode<K, V> : Node<K>
|
||||
public sealed class LeafNode<TK, TV> : Node<TK>
|
||||
{
|
||||
public const int Capacity = 64;
|
||||
public const int MergeThreshold = 8;
|
||||
|
||||
public K[]? Keys;
|
||||
public V[] Values;
|
||||
public TK[]? Keys;
|
||||
public TV[] Values;
|
||||
|
||||
internal long[]? _prefixes;
|
||||
private long[]? _prefixes;
|
||||
|
||||
public override Span<long> AllPrefixes => _prefixes != null ? _prefixes : Span<long>.Empty;
|
||||
|
||||
public LeafNode(OwnerId owner, bool usePrefixes) : base(owner, NodeFlags.IsLeaf | (usePrefixes ? NodeFlags.HasPrefixes : NodeFlags.None))
|
||||
{
|
||||
Keys = new K[Capacity];
|
||||
Values = new V[Capacity];
|
||||
Keys = new TK[Capacity];
|
||||
Values = new TV[Capacity];
|
||||
if (usePrefixes)
|
||||
{
|
||||
_prefixes = new long[Capacity];
|
||||
|
|
@ -119,21 +119,21 @@ public sealed class LeafNode<K, V> : Node<K>
|
|||
}
|
||||
|
||||
// Copy Constructor for CoW
|
||||
private LeafNode(LeafNode<K, V> original, OwnerId newOwner)
|
||||
private LeafNode(LeafNode<TK, TV> original, OwnerId newOwner)
|
||||
: base(newOwner, original.Header.Flags)
|
||||
{
|
||||
Keys = new K[Capacity];
|
||||
Values = new V[Capacity];
|
||||
Keys = new TK[Capacity];
|
||||
Values = new TV[Capacity];
|
||||
Header.Count = original.Header.Count; _prefixes = new long[Capacity];
|
||||
|
||||
// Copy data
|
||||
Array.Copy(original.Keys, Keys, original.Header.Count);
|
||||
Array.Copy(original.Keys!, Keys, original.Header.Count);
|
||||
Array.Copy(original.Values, Values, original.Header.Count);
|
||||
if (original._prefixes != null)
|
||||
Array.Copy(original._prefixes, _prefixes, original.Header.Count);
|
||||
}
|
||||
|
||||
public override Node<K> EnsureEditable(OwnerId transactionId)
|
||||
public override Node<TK> EnsureEditable(OwnerId transactionId)
|
||||
{
|
||||
// CASE 1: Persistent Mode (transactionId is None).
|
||||
// We MUST create a copy, because we cannot distinguish "Shared Immutable Node (0)"
|
||||
|
|
@ -142,7 +142,7 @@ public sealed class LeafNode<K, V> : Node<K>
|
|||
// we won't copy the same fresh node twice.
|
||||
if (transactionId == OwnerId.None)
|
||||
{
|
||||
return new LeafNode<K, V>(this, OwnerId.None);
|
||||
return new LeafNode<TK, TV>(this, OwnerId.None);
|
||||
}
|
||||
|
||||
// CASE 2: Transient Mode.
|
||||
|
|
@ -153,26 +153,26 @@ public sealed class LeafNode<K, V> : Node<K>
|
|||
}
|
||||
|
||||
// CASE 3: CoW needed (Ownership mismatch).
|
||||
return new LeafNode<K, V>(this, transactionId);
|
||||
return new LeafNode<TK, TV>(this, transactionId);
|
||||
}
|
||||
|
||||
public override Span<K> GetKeys()
|
||||
public override Span<TK> GetKeys()
|
||||
{
|
||||
return Keys.AsSpan(0, Header.Count);
|
||||
}
|
||||
|
||||
public Span<V> GetValues()
|
||||
public Span<TV> GetValues()
|
||||
{
|
||||
return Values.AsSpan(0, Header.Count);
|
||||
}
|
||||
}
|
||||
|
||||
public class InternalNode<K> : Node<K>
|
||||
public class InternalNode<TK> : Node<TK>
|
||||
{
|
||||
public const int Capacity = 32;
|
||||
|
||||
public KeyBuffer<K> Keys;
|
||||
public NodeBuffer<K> Children;
|
||||
public KeyBuffer<TK> Keys;
|
||||
public NodeBuffer<TK> Children;
|
||||
|
||||
public override Span<long> AllPrefixes => Span<long>.Empty;
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ public class InternalNode<K> : Node<K>
|
|||
}
|
||||
|
||||
// Fixed CoW Constructor
|
||||
protected InternalNode(InternalNode<K> original, OwnerId newOwner, NodeFlags flags)
|
||||
protected InternalNode(InternalNode<TK> original, OwnerId newOwner, NodeFlags flags)
|
||||
: base(newOwner, flags)
|
||||
{
|
||||
Header.Count = original.Header.Count;
|
||||
|
|
@ -195,28 +195,28 @@ public class InternalNode<K> : Node<K>
|
|||
|
||||
// The missing method needed by BTreeFunctions for routing
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public Span<Node<K>> GetChildren()
|
||||
public Span<Node<TK>> GetChildren()
|
||||
{
|
||||
// An internal node always has (Count + 1) children
|
||||
return MemoryMarshal.CreateSpan(ref Children[0], Header.Count + 1);
|
||||
return MemoryMarshal.CreateSpan(ref Children[0]!, Header.Count + 1);
|
||||
}
|
||||
|
||||
public override Span<K> GetKeys() => MemoryMarshal.CreateSpan(ref Keys[0], Header.Count);
|
||||
public override Span<TK> GetKeys() => MemoryMarshal.CreateSpan(ref Keys[0], Header.Count);
|
||||
|
||||
public override Node<K> EnsureEditable(OwnerId transactionId)
|
||||
public override Node<TK> EnsureEditable(OwnerId transactionId)
|
||||
{
|
||||
if (transactionId == OwnerId.None) return new InternalNode<K>(this, OwnerId.None, Header.Flags);
|
||||
if (transactionId == OwnerId.None) return new InternalNode<TK>(this, OwnerId.None, Header.Flags);
|
||||
if (Header.Owner == transactionId) return this;
|
||||
return new InternalNode<K>(this, transactionId, Header.Flags);
|
||||
return new InternalNode<TK>(this, transactionId, Header.Flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public sealed class PrefixInternalNode<K> : InternalNode<K>
|
||||
public sealed class PrefixInternalNode<TK> : InternalNode<TK>
|
||||
{
|
||||
internal InternalPrefixBuffer _prefixBuffer;
|
||||
internal InternalPrefixBuffer PrefixBuffer;
|
||||
|
||||
public override Span<long> AllPrefixes => MemoryMarshal.CreateSpan(ref _prefixBuffer[0], Capacity);
|
||||
public override Span<long> AllPrefixes => MemoryMarshal.CreateSpan(ref PrefixBuffer[0], Capacity);
|
||||
|
||||
public PrefixInternalNode(OwnerId owner)
|
||||
: base(owner, NodeFlags.HasPrefixes)
|
||||
|
|
@ -224,18 +224,18 @@ public sealed class PrefixInternalNode<K> : InternalNode<K>
|
|||
}
|
||||
|
||||
// CoW Constructor
|
||||
private PrefixInternalNode(PrefixInternalNode<K> original, OwnerId newOwner)
|
||||
private PrefixInternalNode(PrefixInternalNode<TK> original, OwnerId newOwner)
|
||||
: base(original, newOwner, original.Header.Flags)
|
||||
{
|
||||
// Copy the base Keys and Children, then blit the prefix buffer
|
||||
this._prefixBuffer = original._prefixBuffer;
|
||||
this.PrefixBuffer = original.PrefixBuffer;
|
||||
}
|
||||
|
||||
public override Node<K> EnsureEditable(OwnerId transactionId)
|
||||
public override Node<TK> EnsureEditable(OwnerId transactionId)
|
||||
{
|
||||
if (transactionId == OwnerId.None) return new PrefixInternalNode<K>(this, OwnerId.None);
|
||||
if (transactionId == OwnerId.None) return new PrefixInternalNode<TK>(this, OwnerId.None);
|
||||
if (Header.Owner == transactionId) return this;
|
||||
return new PrefixInternalNode<K>(this, transactionId);
|
||||
return new PrefixInternalNode<TK>(this, transactionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue