wasSharp – Blame information for rev 44

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