Skip to content

Commit 8b3ca6d

Browse files
committed
TreeMethods and ListMethods of MemoryManagers are now separate classes. Refactoring, performance optimizations.
1 parent 8f450bf commit 8b3ca6d

20 files changed

+1264
-1064
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
2+
3+
namespace Platform.Data.Doublets.ResizableDirectMemory
4+
{
5+
public interface ILinksListMethods<TLink>
6+
{
7+
void Detach(TLink freeLink);
8+
void AttachAsFirst(TLink link);
9+
}
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
5+
6+
namespace Platform.Data.Doublets.ResizableDirectMemory
7+
{
8+
public interface ILinksTreeMethods<TLink>
9+
{
10+
TLink CountUsages(TLink link);
11+
TLink Search(TLink source, TLink target);
12+
TLink EachUsage(TLink source, Func<IList<TLink>, TLink> handler);
13+
void Detach(ref TLink firstAsSource, TLink linkIndex);
14+
void Attach(ref TLink firstAsSource, TLink linkIndex);
15+
}
16+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
using System;
2+
using System.Text;
3+
using System.Collections.Generic;
4+
using System.Runtime.CompilerServices;
5+
using Platform.Numbers;
6+
using Platform.Collections.Methods.Trees;
7+
using static System.Runtime.CompilerServices.Unsafe;
8+
9+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
10+
11+
namespace Platform.Data.Doublets.ResizableDirectMemory
12+
{
13+
public unsafe abstract class LinksAVLBalancedTreeMethodsBase<TLink> : SizedAndThreadedAVLBalancedTreeMethods<TLink>
14+
{
15+
private readonly ResizableDirectMemoryLinks<TLink> _memory;
16+
private readonly LinksConstants<TLink> _constants;
17+
protected readonly byte* Links;
18+
protected readonly byte* Header;
19+
20+
public LinksAVLBalancedTreeMethodsBase(ResizableDirectMemoryLinks<TLink> memory, byte* links, byte* header)
21+
{
22+
Links = links;
23+
Header = header;
24+
_memory = memory;
25+
_constants = memory.Constants;
26+
}
27+
28+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
29+
protected abstract TLink GetTreeRoot();
30+
31+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
32+
protected abstract TLink GetBasePartValue(TLink link);
33+
34+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
35+
protected abstract bool FirstIsToTheRightOfSecond(TLink source, TLink target, TLink rootSource, TLink rootTarget);
36+
37+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
38+
protected abstract bool FirstIsToTheLeftOfSecond(TLink source, TLink target, TLink rootSource, TLink rootTarget);
39+
40+
public TLink this[TLink index]
41+
{
42+
get
43+
{
44+
var root = GetTreeRoot();
45+
if (GreaterOrEqualThan(index, GetSize(root)))
46+
{
47+
return GetZero();
48+
}
49+
while (!EqualToZero(root))
50+
{
51+
var left = GetLeftOrDefault(root);
52+
var leftSize = GetSizeOrZero(left);
53+
if (LessThan(index, leftSize))
54+
{
55+
root = left;
56+
continue;
57+
}
58+
if (IsEquals(index, leftSize))
59+
{
60+
return root;
61+
}
62+
root = GetRightOrDefault(root);
63+
index = Subtract(index, Increment(leftSize));
64+
}
65+
return GetZero(); // TODO: Impossible situation exception (only if tree structure broken)
66+
}
67+
}
68+
69+
/// <summary>
70+
/// Выполняет поиск и возвращает индекс связи с указанными Source (началом) и Target (концом)
71+
/// по дереву (индексу) связей, отсортированному по Source, а затем по Target.
72+
/// </summary>
73+
/// <param name="source">Индекс связи, которая является началом на искомой связи.</param>
74+
/// <param name="target">Индекс связи, которая является концом на искомой связи.</param>
75+
/// <returns>Индекс искомой связи.</returns>
76+
public TLink Search(TLink source, TLink target)
77+
{
78+
var root = GetTreeRoot();
79+
while (!EqualToZero(root))
80+
{
81+
var rootSource = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)root + RawLink<TLink>.SourceOffset);
82+
var rootTarget = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)root + RawLink<TLink>.TargetOffset);
83+
if (FirstIsToTheLeftOfSecond(source, target, rootSource, rootTarget)) // node.Key < root.Key
84+
{
85+
root = GetLeftOrDefault(root);
86+
}
87+
else if (FirstIsToTheRightOfSecond(source, target, rootSource, rootTarget)) // node.Key > root.Key
88+
{
89+
root = GetRightOrDefault(root);
90+
}
91+
else // node.Key == root.Key
92+
{
93+
return root;
94+
}
95+
}
96+
return GetZero();
97+
}
98+
99+
// TODO: Return indices range instead of references count
100+
public TLink CountUsages(TLink link)
101+
{
102+
var root = GetTreeRoot();
103+
var total = GetSize(root);
104+
var totalRightIgnore = GetZero();
105+
while (!EqualToZero(root))
106+
{
107+
var @base = GetBasePartValue(root);
108+
if (LessOrEqualThan(@base, link))
109+
{
110+
root = GetRightOrDefault(root);
111+
}
112+
else
113+
{
114+
totalRightIgnore = Add(totalRightIgnore, Increment(GetRightSize(root)));
115+
root = GetLeftOrDefault(root);
116+
}
117+
}
118+
root = GetTreeRoot();
119+
var totalLeftIgnore = GetZero();
120+
while (!EqualToZero(root))
121+
{
122+
var @base = GetBasePartValue(root);
123+
if (GreaterOrEqualThan(@base, link))
124+
{
125+
root = GetLeftOrDefault(root);
126+
}
127+
else
128+
{
129+
totalLeftIgnore = Add(totalLeftIgnore, Increment(GetLeftSize(root)));
130+
131+
root = GetRightOrDefault(root);
132+
}
133+
}
134+
return Subtract(Subtract(total, totalRightIgnore), totalLeftIgnore);
135+
}
136+
137+
public TLink EachUsage(TLink link, Func<IList<TLink>, TLink> handler)
138+
{
139+
var root = GetTreeRoot();
140+
if (EqualToZero(root))
141+
{
142+
return _constants.Continue;
143+
}
144+
TLink first = GetZero(), current = root;
145+
while (!EqualToZero(current))
146+
{
147+
var @base = GetBasePartValue(current);
148+
if (GreaterOrEqualThan(@base, link))
149+
{
150+
if (IsEquals(@base, link))
151+
{
152+
first = current;
153+
}
154+
current = GetLeftOrDefault(current);
155+
}
156+
else
157+
{
158+
current = GetRightOrDefault(current);
159+
}
160+
}
161+
if (!EqualToZero(first))
162+
{
163+
current = first;
164+
while (true)
165+
{
166+
if (IsEquals(handler(_memory.GetLinkStruct(current)), _constants.Break))
167+
{
168+
return _constants.Break;
169+
}
170+
current = GetNext(current);
171+
if (EqualToZero(current) || !IsEquals(GetBasePartValue(current), link))
172+
{
173+
break;
174+
}
175+
}
176+
}
177+
return _constants.Continue;
178+
}
179+
180+
protected override void PrintNodeValue(TLink node, StringBuilder sb)
181+
{
182+
sb.Append(' ');
183+
sb.Append(Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SourceOffset));
184+
sb.Append('-');
185+
sb.Append('>');
186+
sb.Append(Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.TargetOffset));
187+
}
188+
}
189+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Platform.Unsafe;
2+
using System.Runtime.InteropServices;
3+
4+
namespace Platform.Data.Doublets.ResizableDirectMemory
5+
{
6+
internal struct LinksHeader<TLink>
7+
{
8+
public static readonly long SizeInBytes = Structure<LinksHeader<TLink>>.Size;
9+
public static readonly long AllocatedLinksOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(AllocatedLinks)).ToInt32();
10+
public static readonly long ReservedLinksOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(ReservedLinks)).ToInt32();
11+
public static readonly long FreeLinksOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(FreeLinks)).ToInt32();
12+
public static readonly long FirstFreeLinkOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(FirstFreeLink)).ToInt32();
13+
public static readonly long FirstAsSourceOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(FirstAsSource)).ToInt32();
14+
public static readonly long FirstAsTargetOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(FirstAsTarget)).ToInt32();
15+
public static readonly long LastFreeLinkOffset = Marshal.OffsetOf(typeof(LinksHeader<TLink>), nameof(LastFreeLink)).ToInt32();
16+
17+
public TLink AllocatedLinks;
18+
public TLink ReservedLinks;
19+
public TLink FreeLinks;
20+
public TLink FirstFreeLink;
21+
public TLink FirstAsSource;
22+
public TLink FirstAsTarget;
23+
public TLink LastFreeLink;
24+
public TLink Reserved8;
25+
}
26+
}
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
using System.Runtime.CompilerServices;
2+
using Platform.Numbers;
3+
using static System.Runtime.CompilerServices.Unsafe;
4+
5+
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
6+
7+
namespace Platform.Data.Doublets.ResizableDirectMemory
8+
{
9+
public unsafe class LinksSourcesAVLBalancedTreeMethods<TLink> : LinksAVLBalancedTreeMethodsBase<TLink>, ILinksTreeMethods<TLink>
10+
{
11+
public LinksSourcesAVLBalancedTreeMethods(ResizableDirectMemoryLinks<TLink> memory, byte* links, byte* header) : base(memory, links, header) { }
12+
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
protected unsafe override ref TLink GetLeftReference(TLink node) => ref AsRef<TLink>((void*)(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.LeftAsSourceOffset));
15+
16+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
17+
protected unsafe override ref TLink GetRightReference(TLink node) => ref AsRef<TLink>((void*)(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.RightAsSourceOffset));
18+
19+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
20+
protected override TLink GetLeft(TLink node) => Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.LeftAsSourceOffset);
21+
22+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
23+
protected override TLink GetRight(TLink node) => Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.RightAsSourceOffset);
24+
25+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
26+
protected override TLink GetSize(TLink node)
27+
{
28+
var previousValue = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset);
29+
return Bit<TLink>.PartialRead(previousValue, 5, -5);
30+
}
31+
32+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
33+
protected override void SetLeft(TLink node, TLink left) => Write(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.LeftAsSourceOffset, left);
34+
35+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
36+
protected override void SetRight(TLink node, TLink right) => Write(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.RightAsSourceOffset, right);
37+
38+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
39+
protected override void SetSize(TLink node, TLink size)
40+
{
41+
var linkSizeAsSourceOffset = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset;
42+
var previousValue = Read<TLink>(linkSizeAsSourceOffset);
43+
Write(linkSizeAsSourceOffset, Bit<TLink>.PartialWrite(previousValue, size, 5, -5));
44+
}
45+
46+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
47+
protected override bool GetLeftIsChild(TLink node)
48+
{
49+
var previousValue = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset);
50+
//return (Integer<TLink>)Bit<TLink>.PartialRead(previousValue, 4, 1);
51+
return !EqualityComparer.Equals(Bit<TLink>.PartialRead(previousValue, 4, 1), default);
52+
}
53+
54+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
55+
protected override void SetLeftIsChild(TLink node, bool value)
56+
{
57+
var linkSizeAsSourceOffset = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset;
58+
var previousValue = Read<TLink>(linkSizeAsSourceOffset);
59+
var modified = Bit<TLink>.PartialWrite(previousValue, (Integer<TLink>)value, 4, 1);
60+
Write(linkSizeAsSourceOffset, modified);
61+
}
62+
63+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
64+
protected override bool GetRightIsChild(TLink node)
65+
{
66+
var previousValue = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset);
67+
//return (Integer<TLink>)Bit<TLink>.PartialRead(previousValue, 3, 1);
68+
return !EqualityComparer.Equals(Bit<TLink>.PartialRead(previousValue, 3, 1), default);
69+
}
70+
71+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
72+
protected override void SetRightIsChild(TLink node, bool value)
73+
{
74+
var linkSizeAsSourceOffset = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset;
75+
var previousValue = Read<TLink>(linkSizeAsSourceOffset);
76+
var modified = Bit<TLink>.PartialWrite(previousValue, (Integer<TLink>)value, 3, 1);
77+
Write(linkSizeAsSourceOffset, modified);
78+
}
79+
80+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
81+
protected override sbyte GetBalance(TLink node)
82+
{
83+
unchecked
84+
{
85+
var previousValue = Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset);
86+
var value = (int)(Integer<TLink>)Bit<TLink>.PartialRead(previousValue, 0, 3);
87+
value |= 0xF8 * ((value & 4) >> 2); // if negative, then continue ones to the end of sbyte
88+
return (sbyte)value;
89+
}
90+
}
91+
92+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
93+
protected override void SetBalance(TLink node, sbyte value)
94+
{
95+
var linkSizeAsSourceOffset = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node + RawLink<TLink>.SizeAsSourceOffset;
96+
var previousValue = Read<TLink>(linkSizeAsSourceOffset);
97+
var packagedValue = (TLink)(Integer<TLink>)((((byte)value >> 5) & 4) | value & 3);
98+
var modified = Bit<TLink>.PartialWrite(previousValue, packagedValue, 0, 3);
99+
Write(linkSizeAsSourceOffset, modified);
100+
}
101+
102+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
103+
protected override bool FirstIsToTheLeftOfSecond(TLink first, TLink second)
104+
{
105+
var firstLink = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)first;
106+
var secondLink = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)second;
107+
var firstSource = Read<TLink>(firstLink + RawLink<TLink>.SourceOffset);
108+
var secondSource = Read<TLink>(secondLink + RawLink<TLink>.SourceOffset);
109+
return LessThan(firstSource, secondSource) ||
110+
(IsEquals(firstSource, secondSource) && LessThan(Read<TLink>(firstLink + RawLink<TLink>.TargetOffset), Read<TLink>(secondLink + RawLink<TLink>.TargetOffset)));
111+
}
112+
113+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
114+
protected override bool FirstIsToTheRightOfSecond(TLink first, TLink second)
115+
{
116+
var firstLink = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)first;
117+
var secondLink = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)second;
118+
var firstSource = Read<TLink>(firstLink + RawLink<TLink>.SourceOffset);
119+
var secondSource = Read<TLink>(secondLink + RawLink<TLink>.SourceOffset);
120+
return GreaterThan(firstSource, secondSource) ||
121+
(IsEquals(firstSource, secondSource) && GreaterThan(Read<TLink>(firstLink + RawLink<TLink>.TargetOffset), Read<TLink>(secondLink + RawLink<TLink>.TargetOffset)));
122+
}
123+
124+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
125+
protected override TLink GetTreeRoot() => Read<TLink>(Header + LinksHeader<TLink>.FirstAsSourceOffset);
126+
127+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
128+
protected override TLink GetBasePartValue(TLink link) => Read<TLink>(Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)link + RawLink<TLink>.SourceOffset);
129+
130+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
131+
protected override bool FirstIsToTheLeftOfSecond(TLink firstSource, TLink firstTarget, TLink secondSource, TLink secondTarget) => LessThan(firstSource, secondSource) || (IsEquals(firstSource, secondSource) && LessThan(firstTarget, secondTarget));
132+
133+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
134+
protected override bool FirstIsToTheRightOfSecond(TLink firstSource, TLink firstTarget, TLink secondSource, TLink secondTarget) => GreaterThan(firstSource, secondSource) || (IsEquals(firstSource, secondSource) && GreaterThan(firstTarget, secondTarget));
135+
136+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
137+
protected override void ClearNode(TLink node)
138+
{
139+
byte* link = Links + RawLink<TLink>.SizeInBytes * (Integer<TLink>)node;
140+
Write(link + RawLink<TLink>.LeftAsSourceOffset, Zero);
141+
Write(link + RawLink<TLink>.RightAsSourceOffset, Zero);
142+
Write(link + RawLink<TLink>.SizeAsSourceOffset, Zero);
143+
}
144+
}
145+
}

0 commit comments

Comments
 (0)