-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathAGSConcurrentHashSet.cs
116 lines (95 loc) · 3.03 KB
/
AGSConcurrentHashSet.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
108
109
110
111
112
113
114
115
using System;
using AGS.API;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections;
namespace AGS.Engine
{
public class AGSConcurrentHashSet<TItem> : IConcurrentHashSet<TItem>
{
//We're using a concurrent dictionary with a value we don't care about to simulate a hash set.
private ConcurrentDictionary<TItem, byte> _map;
public AGSConcurrentHashSet(int capacity = 5, bool fireListChangedEvent = true)
{
_map = new ConcurrentDictionary<TItem, byte> (2, capacity);
if (fireListChangedEvent)
OnListChanged = new AGSEvent<AGSHashSetChangedEventArgs<TItem>>();
}
#region IConcurrentCollection implementation
public int Count => _map.Count;
public IBlockingEvent<AGSHashSetChangedEventArgs<TItem>> OnListChanged { get; }
private void onListChanged(TItem item, ListChangeType changeType)
{
var onListChanged = OnListChanged;
if (onListChanged == null) return;
onListChanged.Invoke(new AGSHashSetChangedEventArgs<TItem>(changeType, item));
}
private void onListChanged(List<TItem> items, ListChangeType changeType)
{
var onListChanged = OnListChanged;
if (onListChanged == null) return;
onListChanged.Invoke(new AGSHashSetChangedEventArgs<TItem>(changeType, items));
}
public bool Add(TItem item)
{
bool added = _map.TryAdd(item, 0);
if (added) onListChanged(item, ListChangeType.Add);
return added;
}
public int AddRange(List<TItem> items)
{
List<TItem> addedItems = new List<TItem>(items.Count);
foreach (var item in items)
{
if (_map.TryAdd(item, 0))
{
addedItems.Add(item);
}
}
if (addedItems.Count > 0) onListChanged(addedItems, ListChangeType.Add);
return addedItems.Count;
}
public bool Remove(TItem item)
{
bool removed = _map.TryRemove(item, out byte _);
if (removed) onListChanged(item, ListChangeType.Remove);
return removed;
}
public void RemoveAll(Predicate<TItem> shouldRemove)
{
foreach (var item in _map.Keys)
{
if (shouldRemove(item)) Remove(item);
}
}
public bool Contains(TItem item) => _map.ContainsKey(item);
public void Clear()
{
RemoveAll(_ => true);
}
#endregion
#region IEnumerable implementation
public IEnumerator<TItem> GetEnumerator()
{
var enumerator = _map.GetEnumerator();
try
{
while (enumerator.MoveNext())
{
yield return enumerator.Current.Key;
}
}
finally
{
enumerator.Dispose();
}
}
#endregion
#region IEnumerable implementation
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)_map.Keys).GetEnumerator();
}
#endregion
}
}