wasSharp – Diff between revs 39 and 44

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