-
Notifications
You must be signed in to change notification settings - Fork 0
/
BTreeContext.cs
107 lines (89 loc) · 2.98 KB
/
BTreeContext.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
namespace HeapsAndBTrees
{
public interface IVirtualNode<T, TT, TKey>
where T : IActualNode<TT, TKey>
where TT : INode<TKey>
where TKey : IComparable
{
public T Node { get; }
public bool IsDirty { get; }
}
public interface IActualNode<T, TKey>
where T : INode<TKey>
where TKey : IComparable
{
}
public class BTreeContext<TKey, TValue, TNode, TVirtual, TActual> : IDisposable
where TKey : IComparable
where TNode : INode<TKey>
where TActual : IActualNode<TNode, TKey>, TNode
where TVirtual : IVirtualNode<TActual, TNode, TKey>, TNode
{
private List<TVirtual> _bufferedNodes = new List<TVirtual>();
private int _bufferSize;
public TVirtual Root { get; protected set; }
private BTreeOperation _operation;
private IBTree<TKey, TValue, TNode, TVirtual, TActual> _tree;
private Action<TNode, BTreeOperation> _read;
private Action<TNode, BTreeOperation> _write;
private Func<TActual, BTreeContext<TKey, TValue, TNode, TVirtual, TActual>, TVirtual> _wrapperFactory;
private void UpdateRoot(TActual root)
{
Root = _wrapperFactory(root, this);
}
public BTreeContext(IBTree<TKey, TValue, TNode, TVirtual, TActual> tree,
Action<TNode, BTreeOperation> read, Action<TNode, BTreeOperation> write,
Func<TActual, BTreeContext<TKey, TValue, TNode, TVirtual, TActual>, TVirtual> wrapperFactory,
TActual root, BTreeOperation operation, int bufferSize)
{
_read = read;
_write = write;
_wrapperFactory = wrapperFactory;
_bufferSize = bufferSize;
_bufferedNodes = new List<TVirtual>();
_operation = operation;
UpdateRoot(root);
_tree = tree;
_tree.OnRootChanged += UpdateRoot;
}
private void Pop()
{
var node = _bufferedNodes[0];
if (node.IsDirty)
{
_write(node.Node, _operation);
}
_bufferedNodes.RemoveAt(0);
}
private void Push(TVirtual virtualNode)
{
_read(virtualNode.Node, _operation);
_bufferedNodes.Add(virtualNode);
}
private bool IsLoaded(TVirtual node) => node as object == Root as object || _bufferedNodes.Contains(node);
public void Actualize(TVirtual virtualNode)
{
if (IsLoaded(virtualNode))
{
return;
}
if (_bufferedNodes.Count == _bufferSize)
{
Pop();
}
Push(virtualNode);
}
private void Commit()
{
while (_bufferedNodes.Count != 0)
{
Pop();
}
}
public void Dispose()
{
_tree.OnRootChanged -= UpdateRoot;
Commit();
}
}
}