wasSharp – Diff between revs 44 and 54

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 44 Rev 54
1 /////////////////////////////////////////////////////////////////////////// 1 ///////////////////////////////////////////////////////////////////////////
2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // 2 // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 //
3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // 3 // Please see: http://www.gnu.org/licenses/gpl.html for legal details, //
4 // rights of fair usage, the disclaimer and warranty conditions. // 4 // rights of fair usage, the disclaimer and warranty conditions. //
5 /////////////////////////////////////////////////////////////////////////// 5 ///////////////////////////////////////////////////////////////////////////
6   6  
7 using System; 7 using System;
8 using System.Threading; 8 using System.Threading;
9 using System.Collections; 9 using System.Collections;
10 using System.Collections.Generic; 10 using System.Collections.Generic;
11 using System.Collections.Specialized; 11 using System.Collections.Specialized;
12 using System.Linq; 12 using System.Linq;
13   13  
14 namespace wasSharp.Collections.Specialized 14 namespace wasSharp.Collections.Specialized
15 { 15 {
16 /////////////////////////////////////////////////////////////////////////// 16 ///////////////////////////////////////////////////////////////////////////
17 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // 17 // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 //
18 /////////////////////////////////////////////////////////////////////////// 18 ///////////////////////////////////////////////////////////////////////////
19 /// <summary> 19 /// <summary>
20 /// An implementation of an observable HashSet. 20 /// An implementation of an observable HashSet.
21 /// </summary> 21 /// </summary>
22 /// <typeparam name="T">the object type</typeparam> 22 /// <typeparam name="T">the object type</typeparam>
23 public class ObservableHashSet<T> : ICollection<T>, INotifyCollectionChanged, IEnumerable<T> 23 public class ObservableConcurrentHashSet<T> : ICollection<T>, INotifyCollectionChanged, IEnumerable<T>
24 { 24 {
25 private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); 25 private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
26 private readonly HashSet<T> store = new HashSet<T>(); 26 private readonly HashSet<T> store = new HashSet<T>();
27   27  
28 public ObservableHashSet(HashSet<T> set) 28 public ObservableConcurrentHashSet(HashSet<T> set)
29 { 29 {
30 _lock.EnterWriteLock(); 30 _lock.EnterWriteLock();
31 try 31 try
32 { 32 {
33 UnionWith(set); 33 UnionWith(set);
34 } 34 }
35 finally 35 finally
36 { 36 {
37 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 37 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
38 } 38 }
39 } 39 }
40   40  
41 public ObservableHashSet() 41 public ObservableConcurrentHashSet()
42 { 42 {
43 } 43 }
44   44  
45 public ObservableHashSet(T item) 45 public ObservableConcurrentHashSet(T item)
46 { 46 {
47 _lock.EnterWriteLock(); 47 _lock.EnterWriteLock();
48 try 48 try
49 { 49 {
50 Add(item); 50 Add(item);
51 } 51 }
52 finally 52 finally
53 { 53 {
54 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 54 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
55 } 55 }
56 } 56 }
57   57  
58 public ObservableHashSet(ObservableHashSet<T> other) 58 public ObservableConcurrentHashSet(ObservableConcurrentHashSet<T> other)
59 { 59 {
60 _lock.EnterWriteLock(); 60 _lock.EnterWriteLock();
61 try 61 try
62 { 62 {
63 UnionWith(other); 63 UnionWith(other);
64 } 64 }
65 finally 65 finally
66 { 66 {
67 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 67 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
68 } 68 }
69 } 69 }
70   70  
71 public ObservableHashSet(IEnumerable<T> list) 71 public ObservableConcurrentHashSet(IEnumerable<T> list)
72 { 72 {
73 _lock.EnterWriteLock(); 73 _lock.EnterWriteLock();
74 try 74 try
75 { 75 {
76 UnionWith(list); 76 UnionWith(list);
77 } 77 }
78 finally 78 finally
79 { 79 {
80 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 80 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
81 } 81 }
82 } 82 }
83   83  
84 public bool IsVirgin { get; private set; } = true; 84 public bool IsVirgin { get; private set; } = true;
85   85  
86 public IEnumerator<T> GetEnumerator() 86 public IEnumerator<T> GetEnumerator()
87 { 87 {
88 _lock.EnterReadLock(); 88 _lock.EnterReadLock();
89 try 89 try
90 { 90 {
91 using (var enumerator = store.GetEnumerator()) 91 using (var enumerator = store.GetEnumerator())
92 { 92 {
93 while (enumerator.MoveNext()) 93 while (enumerator.MoveNext())
94 yield return enumerator.Current; 94 yield return enumerator.Current;
95 } 95 }
96 } 96 }
97 finally 97 finally
98 { 98 {
99 if (_lock.IsReadLockHeld) _lock.ExitReadLock(); 99 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
100 } 100 }
101 } 101 }
102   102  
103 IEnumerator IEnumerable.GetEnumerator() 103 IEnumerator IEnumerable.GetEnumerator()
104 { 104 {
105 _lock.EnterReadLock(); 105 _lock.EnterReadLock();
106 try 106 try
107 { 107 {
108 using (var enumerator = store.GetEnumerator()) 108 using (var enumerator = store.GetEnumerator())
109 { 109 {
110 while (enumerator.MoveNext()) 110 while (enumerator.MoveNext())
111 yield return enumerator.Current; 111 yield return enumerator.Current;
112 } 112 }
113 } 113 }
114 finally 114 finally
115 { 115 {
116 if (_lock.IsReadLockHeld) _lock.ExitReadLock(); 116 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
117 } 117 }
118 } 118 }
119   119  
120 public void Add(T item) 120 public void Add(T item)
121 { 121 {
122 _lock.EnterWriteLock(); 122 _lock.EnterWriteLock();
123 try 123 try
124 { 124 {
125 store.Add(item); 125 store.Add(item);
126 } 126 }
127 finally 127 finally
128 { 128 {
129 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 129 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
130 } 130 }
131 IsVirgin = false; 131 IsVirgin = false;
132 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); 132 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item));
133 } 133 }
134   134  
135 public void Clear() 135 public void Clear()
136 { 136 {
137 _lock.EnterWriteLock(); 137 _lock.EnterWriteLock();
138 try 138 try
139 { 139 {
140 store.Clear(); 140 store.Clear();
141 } 141 }
142 finally 142 finally
143 { 143 {
144 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 144 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
145 } 145 }
146 if (!IsVirgin) 146 if (!IsVirgin)
147 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 147 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
148 IsVirgin = false; 148 IsVirgin = false;
149 } 149 }
150   150  
151 public bool Contains(T item) 151 public bool Contains(T item)
152 { 152 {
153 _lock.EnterReadLock(); 153 _lock.EnterReadLock();
154 try 154 try
155 { 155 {
156 return store.Contains(item); 156 return store.Contains(item);
157 } 157 }
158 finally 158 finally
159 { 159 {
160 if (_lock.IsReadLockHeld) _lock.ExitReadLock(); 160 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
161 } 161 }
162 } 162 }
163   163  
164 public void CopyTo(T[] array, int arrayIndex) 164 public void CopyTo(T[] array, int arrayIndex)
165 { 165 {
166 _lock.EnterReadLock(); 166 _lock.EnterReadLock();
167 try 167 try
168 { 168 {
169 store.CopyTo(array, arrayIndex); 169 store.CopyTo(array, arrayIndex);
170 } 170 }
171 finally 171 finally
172 { 172 {
173 if (_lock.IsReadLockHeld) _lock.ExitReadLock(); 173 if (_lock.IsReadLockHeld) _lock.ExitReadLock();
174 } 174 }
175 } 175 }
176   176  
177 public bool Remove(T item) 177 public bool Remove(T item)
178 { 178 {
179 _lock.EnterWriteLock(); 179 _lock.EnterWriteLock();
180 bool removed; 180 bool removed;
181 try 181 try
182 { 182 {
183 removed = store.Remove(item); 183 removed = store.Remove(item);
184 } 184 }
185 finally 185 finally
186 { 186 {
187 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 187 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
188 } 188 }
189 IsVirgin = false; 189 IsVirgin = false;
190 if (removed) 190 if (removed)
191 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); 191 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item));
192 return removed; 192 return removed;
193 } 193 }
194   194  
195 public int Count => store.Count; 195 public int Count => store.Count();
196   196  
197 public bool IsReadOnly => false; 197 public bool IsReadOnly => false;
198   198  
199 public event NotifyCollectionChangedEventHandler CollectionChanged; 199 public event NotifyCollectionChangedEventHandler CollectionChanged;
200   200  
201 public void UnionWith(IEnumerable<T> list) 201 public void UnionWith(IEnumerable<T> list)
202 { 202 {
203 var added = new List<T>(list.Except(store)); 203 var added = new List<T>(list.Except(store));
204 _lock.EnterWriteLock(); 204 _lock.EnterWriteLock();
205 try 205 try
206 { 206 {
207 store.UnionWith(added); 207 store.UnionWith(added);
208 } 208 }
209 finally 209 finally
210 { 210 {
211 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 211 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
212 } 212 }
213 if (!IsVirgin && added.Any()) 213 if (!IsVirgin && added.Any())
214 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added)); 214 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, added));
215 IsVirgin = false; 215 IsVirgin = false;
216 } 216 }
217   217  
218 private void OnCollectionChanged(NotifyCollectionChangedEventArgs args) 218 private void OnCollectionChanged(NotifyCollectionChangedEventArgs args)
219 { 219 {
220 CollectionChanged?.Invoke(this, args); 220 CollectionChanged?.Invoke(this, args);
221 } 221 }
222   222  
223 public void ExceptWith(IEnumerable<T> list) 223 public void ExceptWith(IEnumerable<T> list)
224 { 224 {
225 var removed = new List<T>(list.Intersect(store)); 225 var removed = new List<T>(list.Intersect(store));
226 _lock.EnterWriteLock(); 226 _lock.EnterWriteLock();
227 try 227 try
228 { 228 {
229 store.ExceptWith(removed); 229 store.ExceptWith(removed);
230 } 230 }
231 finally 231 finally
232 { 232 {
233 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 233 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
234 } 234 }
235 if (!IsVirgin && removed.Any()) 235 if (!IsVirgin && removed.Any())
236 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, 236 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,
237 removed)); 237 removed));
238 IsVirgin = false; 238 IsVirgin = false;
239 } 239 }
240   240  
241 public void RemoveWhere(Func<T, bool> func) 241 public void RemoveWhere(Func<T, bool> func)
242 { 242 {
243 var removed = new List<T>(store.Where(func)); 243 var removed = new List<T>(store.Where(func));
244 _lock.EnterWriteLock(); 244 _lock.EnterWriteLock();
245 try 245 try
246 { 246 {
247 store.ExceptWith(removed); 247 store.ExceptWith(removed);
248 } 248 }
249 finally 249 finally
250 { 250 {
251 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 251 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
252 } 252 }
253 if (!IsVirgin && removed.Any()) 253 if (!IsVirgin && removed.Any())
254 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, 254 OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove,
255 removed)); 255 removed));
256 IsVirgin = false; 256 IsVirgin = false;
257 } 257 }
258   258  
259 public IEnumerable<T> AsEnumerable() 259 public IEnumerable<T> AsEnumerable()
260 { 260 {
261 _lock.EnterWriteLock(); 261 _lock.EnterWriteLock();
262 try 262 try
263 { 263 {
264 return store.AsEnumerable(); 264 return store.AsEnumerable();
265 } 265 }
266 finally 266 finally
267 { 267 {
268 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); 268 if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
269 } 269 }
270 } 270 }
271 } 271 }
272 } 272 }
273   273