Skip to content

Commit be39e78

Browse files
Merge pull request #2 from Open-NET-Libraries/experimental
Experimental
2 parents f06cd26 + 3de043d commit be39e78

File tree

105 files changed

+8889
-8403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

105 files changed

+8889
-8403
lines changed

.editorconfig

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ csharp_prefer_static_local_function = true
105105
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
106106

107107
# Code-block preferences
108-
csharp_prefer_braces = when_multiline
109-
csharp_prefer_simple_using_statement = true
108+
csharp_prefer_braces = when_multiline:silent
109+
csharp_prefer_simple_using_statement = true:suggestion
110110
csharp_style_namespace_declarations = file_scoped:suggestion
111111

112112
# Expression-level preferences
@@ -224,4 +224,14 @@ dotnet_naming_style.begins_with_i.capitalization = pascal_case
224224
dotnet_diagnostic.IDE0057.severity = silent
225225

226226
dotnet_diagnostic.CS1591.severity = suggestion
227-
#dotnet_diagnostic.SA0001.severity = suggestion
227+
csharp_style_prefer_method_group_conversion = true:silent
228+
csharp_style_prefer_top_level_statements = true:silent
229+
#dotnet_diagnostic.SA0001.severity = suggestion
230+
[*.{cs,vb}]
231+
dotnet_style_coalesce_expression = true:warning
232+
dotnet_style_operator_placement_when_wrapping = beginning_of_line
233+
tab_width = 4
234+
indent_size = 4
235+
end_of_line = crlf
236+
dotnet_style_null_propagation = true:warning
237+
indent_style = tab

Open.Collections.sln

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Open.Collections.Tests", "t
99
EndProject
1010
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Open.Collections.Benchmarking", "benchmarking\Open.Collections.Benchmarking.csproj", "{A3EA31B7-6E9B-4780-808A-BBDF116521EA}"
1111
EndProject
12-
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Open.Collections.Trie", "Trie\Open.Collections.Trie.csproj", "{A93C5840-7258-48C6-A223-AADCC29B838B}"
12+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Open.Collections.Trie", "Trie\Open.Collections.Trie.csproj", "{A93C5840-7258-48C6-A223-AADCC29B838B}"
13+
EndProject
14+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EDF93B9B-F566-4ED3-8E50-3BCF1DA520FD}"
15+
ProjectSection(SolutionItems) = preProject
16+
.editorconfig = .editorconfig
17+
EndProjectSection
1318
EndProject
1419
Global
1520
GlobalSection(SolutionConfigurationPlatforms) = preSolution

Trie/ConcurrentTrie.cs

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,57 @@
11
using System.Collections.Concurrent;
22
using System.Collections.Generic;
3-
using System.Threading;
43

54
namespace Open.Collections;
65

76
/// <summary>
87
/// A generic Trie collection.
98
/// </summary>
109
public sealed class ConcurrentTrie<TKey, TValue>
11-
: TrieBase<TKey, TValue>
10+
: TrieBase<TKey, TValue>
11+
where TKey : notnull
1212
{
13-
/// <summary>
14-
/// Constructs a <see cref="ConcurrentTrie{TKey, TValue}"/>.
15-
/// </summary>
16-
public ConcurrentTrie()
17-
: base(() => new Node())
18-
{ }
19-
20-
private sealed class Node : NodeBase
21-
{
22-
private ConcurrentDictionary<TKey, ITrieNode<TKey, TValue>>? _children;
23-
24-
public override ITrieNode<TKey, TValue> GetOrAddChild(TKey key)
25-
{
26-
var children = LazyInitializer.EnsureInitialized(ref _children, ()=>
27-
{
28-
var c = new ConcurrentDictionary<TKey, ITrieNode<TKey, TValue>>();
29-
Children = c;
30-
return c;
31-
})!;
32-
33-
return children.GetOrAdd(key, _ => new Node());
34-
}
35-
}
13+
/// <summary>
14+
/// Constructs a <see cref="ConcurrentTrie{TKey, TValue}"/>.
15+
/// </summary>
16+
public ConcurrentTrie(IEqualityComparer<TKey>? equalityComparer = null)
17+
: base(() => new Node(equalityComparer))
18+
{ }
19+
20+
private sealed class Node : NodeBase
21+
{
22+
public Node(IEqualityComparer<TKey>? equalityComparer)
23+
=> _equalityComparer = equalityComparer;
24+
25+
private readonly object _valueSync = new();
26+
27+
protected override void SetValue(TValue value)
28+
{
29+
lock (_valueSync) base.SetValue(value);
30+
}
31+
32+
private readonly object _childSync = new();
33+
34+
private readonly IEqualityComparer<TKey>? _equalityComparer;
35+
private ConcurrentDictionary<TKey, ITrieNode<TKey, TValue>>? _children;
36+
37+
protected override void UpdateRecent(TKey key, ITrieNode<TKey, TValue> child)
38+
{
39+
lock (_childSync) base.UpdateRecent(key, child);
40+
}
41+
42+
public override ITrieNode<TKey, TValue> GetOrAddChild(TKey key)
43+
{
44+
var children = _children;
45+
if (children is null)
46+
{
47+
lock (_childSync)
48+
{
49+
if (children is null)
50+
Children = _children = children = _equalityComparer is null ? new() : new(_equalityComparer);
51+
}
52+
}
53+
54+
return children.GetOrAdd(key, _ => new Node(_equalityComparer));
55+
}
56+
}
3657
}

Trie/HybridDictionary.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
namespace Open.Collections.Trie;
7+
internal class HybridDictionary<TKey, TValue> : IDictionary<TKey, TValue>
8+
{
9+
private readonly struct Entry
10+
{
11+
public Entry(TKey key, TValue value)
12+
{
13+
Key = key;
14+
Value = value;
15+
}
16+
17+
public TKey Key { get; }
18+
public TValue Value { get; }
19+
}
20+
21+
private const int SEARCH_THRESHOLD = 12;
22+
23+
private Entry[]? _list;
24+
private readonly Dictionary<TKey, TValue> _dictionary;
25+
26+
public ICollection<TKey> Keys => _dictionary.Keys;
27+
28+
public ICollection<TValue> Values => _dictionary.Values;
29+
30+
public int Count => _dictionary.Count;
31+
32+
public bool IsReadOnly => ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).IsReadOnly;
33+
34+
public HybridDictionary()
35+
{
36+
_list = new Entry[SEARCH_THRESHOLD];
37+
_dictionary = new();
38+
}
39+
40+
public TValue this[TKey key]
41+
{
42+
get => TryGetValue(key, out var value) ? value : throw new KeyNotFoundException();
43+
set => Add(key, value);
44+
}
45+
46+
public void Add(TKey key, TValue value)
47+
{
48+
_dictionary.Add(key, value);
49+
int count = _dictionary.Count;
50+
var list = _list;
51+
if (list is null) return;
52+
if (count == SEARCH_THRESHOLD)
53+
_list = null;
54+
else
55+
list[count - 1] = new(key, value);
56+
}
57+
58+
public bool TryGetValue(TKey key, out TValue value)
59+
{
60+
if (key is null) throw new ArgumentNullException(nameof(key));
61+
62+
var list = _list;
63+
if(list is not null)
64+
{
65+
foreach(var e in list)
66+
{
67+
if(key.Equals(e.Key))
68+
{
69+
value = e.Value;
70+
return true;
71+
}
72+
}
73+
74+
value = default!;
75+
return false;
76+
}
77+
78+
return _dictionary.TryGetValue(key, out value);
79+
}
80+
81+
public bool Remove(TKey key) => throw new NotSupportedException();
82+
83+
public void Clear()
84+
{
85+
_dictionary.Clear();
86+
_list = new Entry[SEARCH_THRESHOLD];
87+
}
88+
89+
public bool ContainsKey(TKey key) => _dictionary.ContainsKey(key);
90+
public void Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
91+
public bool Contains(KeyValuePair<TKey, TValue> item) => _dictionary.Contains(item);
92+
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => ((ICollection<KeyValuePair<TKey, TValue>>)_dictionary).CopyTo(array, arrayIndex);
93+
public bool Remove(KeyValuePair<TKey, TValue> item) => throw new NotSupportedException();
94+
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => _dictionary.GetEnumerator();
95+
IEnumerator IEnumerable.GetEnumerator() => _dictionary.GetEnumerator();
96+
}

0 commit comments

Comments
 (0)