wasSharp – Blame information for rev 39
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
10 | office | 1 | /////////////////////////////////////////////////////////////////////////// |
2 | // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // |
||
3 | // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
||
4 | // rights of fair usage, the disclaimer and warranty conditions. // |
||
5 | /////////////////////////////////////////////////////////////////////////// |
||
6 | |||
7 | using System; |
||
39 | office | 8 | using System.Threading; |
10 | office | 9 | using System.Collections; |
10 | using System.Collections.Generic; |
||
11 | using System.Collections.Specialized; |
||
12 | using System.Linq; |
||
13 | |||
14 | namespace wasSharp.Collections.Specialized |
||
15 | { |
||
16 | /////////////////////////////////////////////////////////////////////////// |
||
17 | // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // |
||
18 | /////////////////////////////////////////////////////////////////////////// |
||
19 | /// <summary> |
||
20 | /// An implementation of an observable HashSet. |
||
21 | /// </summary> |
||
22 | /// <typeparam name="T">the object type</typeparam> |
||
23 | office | 23 | public class ObservableHashSet<T> : ICollection<T>, INotifyCollectionChanged, IEnumerable<T> |
10 | office | 24 | { |
39 | office | 25 | private readonly ReaderWriterLockSlim SyncRoot = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
10 | office | 26 | private readonly HashSet<T> store = new HashSet<T>(); |
27 | |||
28 | public ObservableHashSet(HashSet<T> set) |
||
29 | { |
||
39 | office | 30 | SyncRoot.EnterWriteLock(); |
10 | office | 31 | UnionWith(set); |
39 | office | 32 | SyncRoot.ExitWriteLock(); |
10 | office | 33 | } |
34 | |||
35 | public ObservableHashSet() |
||
36 | { |
||
37 | } |
||
38 | |||
39 | public ObservableHashSet(T item) |
||
40 | { |
||
39 | office | 41 | SyncRoot.EnterWriteLock(); |
10 | office | 42 | Add(item); |
39 | office | 43 | SyncRoot.ExitWriteLock(); |
10 | office | 44 | } |
45 | |||
46 | public ObservableHashSet(ObservableHashSet<T> other) |
||
47 | { |
||
39 | office | 48 | SyncRoot.EnterWriteLock(); |
10 | office | 49 | UnionWith(other); |
39 | office | 50 | SyncRoot.ExitWriteLock(); |
10 | office | 51 | } |
52 | |||
53 | public ObservableHashSet(IEnumerable<T> list) |
||
54 | { |
||
39 | office | 55 | SyncRoot.EnterWriteLock(); |
10 | office | 56 | UnionWith(list); |
39 | office | 57 | SyncRoot.ExitWriteLock(); |
10 | office | 58 | } |
59 | |||
60 | public bool IsVirgin { get; private set; } = true; |
||
61 | |||
62 | public IEnumerator<T> GetEnumerator() |
||
63 | { |
||
39 | office | 64 | SyncRoot.EnterReadLock(); |
65 | var enumerator = store.GetEnumerator(); |
||
66 | SyncRoot.ExitReadLock(); |
||
67 | return enumerator; |
||
10 | office | 68 | } |
69 | |||
70 | IEnumerator IEnumerable.GetEnumerator() |
||
71 | { |
||
39 | office | 72 | SyncRoot.EnterReadLock(); |
73 | var enumerator = GetEnumerator(); |
||
74 | SyncRoot.ExitReadLock(); |
||
75 | return enumerator; |
||
10 | office | 76 | } |
77 | |||
78 | public void Add(T item) |
||
79 | { |
||
39 | office | 80 | SyncRoot.EnterWriteLock(); |
10 | office | 81 | store.Add(item); |
39 | office | 82 | SyncRoot.ExitWriteLock(); |
10 | office | 83 | IsVirgin = false; |
84 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); |
||
85 | } |
||
86 | |||
87 | public void Clear() |
||
88 | { |
||
39 | office | 89 | SyncRoot.EnterWriteLock(); |
10 | office | 90 | store.Clear(); |
39 | office | 91 | SyncRoot.ExitWriteLock(); |
10 | office | 92 | if (!IsVirgin) |
93 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); |
||
94 | IsVirgin = false; |
||
95 | } |
||
96 | |||
97 | public bool Contains(T item) |
||
98 | { |
||
39 | office | 99 | SyncRoot.EnterReadLock(); |
100 | var contains = store.Contains(item); |
||
101 | SyncRoot.ExitReadLock(); |
||
102 | return contains; |
||
10 | office | 103 | } |
104 | |||
105 | public void CopyTo(T[] array, int arrayIndex) |
||
106 | { |
||
39 | office | 107 | SyncRoot.EnterReadLock(); |
10 | office | 108 | store.CopyTo(array, arrayIndex); |
39 | office | 109 | SyncRoot.ExitReadLock(); |
10 | office | 110 | } |
111 | |||
112 | public bool Remove(T item) |
||
113 | { |
||
39 | office | 114 | SyncRoot.EnterWriteLock(); |
10 | office | 115 | var removed = store.Remove(item); |
39 | office | 116 | SyncRoot.ExitWriteLock(); |
10 | office | 117 | IsVirgin = false; |
118 | if (removed) |
||
119 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); |
||
120 | return removed; |
||
121 | } |
||
122 | |||
123 | public int Count => store.Count; |
||
124 | |||
125 | public bool IsReadOnly => false; |
||
126 | |||
127 | public event NotifyCollectionChangedEventHandler CollectionChanged; |
||
128 | |||
129 | public void UnionWith(IEnumerable<T> list) |
||
130 | { |
||
131 | var added = new List<T>(list.Except(store)); |
||
39 | office | 132 | SyncRoot.EnterWriteLock(); |
10 | office | 133 | store.UnionWith(added); |
39 | office | 134 | SyncRoot.ExitWriteLock(); |
10 | office | 135 | if (!IsVirgin && added.Any()) |
136 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added)); |
||
137 | IsVirgin = false; |
||
138 | } |
||
139 | |||
140 | private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) |
||
141 | { |
||
142 | CollectionChanged?.Invoke(this, args); |
||
143 | } |
||
144 | |||
145 | public void ExceptWith(IEnumerable<T> list) |
||
146 | { |
||
147 | var removed = new List<T>(list.Intersect(store)); |
||
39 | office | 148 | SyncRoot.EnterWriteLock(); |
10 | office | 149 | store.ExceptWith(removed); |
39 | office | 150 | SyncRoot.ExitWriteLock(); |
10 | office | 151 | if (!IsVirgin && removed.Any()) |
152 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, |
||
153 | removed)); |
||
154 | IsVirgin = false; |
||
155 | } |
||
156 | |||
157 | public void RemoveWhere(Func<T, bool> func) |
||
158 | { |
||
159 | var removed = new List<T>(store.Where(func)); |
||
39 | office | 160 | SyncRoot.EnterWriteLock(); |
10 | office | 161 | store.ExceptWith(removed); |
39 | office | 162 | SyncRoot.ExitWriteLock(); |
10 | office | 163 | if (!IsVirgin && removed.Any()) |
164 | OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, |
||
165 | removed)); |
||
166 | IsVirgin = false; |
||
167 | } |
||
23 | office | 168 | |
169 | public IEnumerable<T> AsEnumerable() |
||
170 | { |
||
39 | office | 171 | SyncRoot.EnterWriteLock(); |
172 | var enumerable = store.AsEnumerable(); |
||
173 | SyncRoot.ExitWriteLock(); |
||
174 | return enumerable; |
||
23 | office | 175 | } |
10 | office | 176 | } |
27 | office | 177 | } |