wasSharp – Diff between revs 40 and 44
?pathlinks?
Rev 40 | 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 | // Based on work by Ben Mosher |
6 | // Based on work by Ben Mosher |
|
7 | |
7 | |
|
8 | using System; |
8 | using System; |
|
9 | using System.Collections; |
9 | using System.Collections; |
|
10 | using System.Collections.Generic; |
10 | using System.Collections.Generic; |
|
11 | using System.Threading; |
11 | using System.Threading; |
|
12 | using System.Linq; |
- | ||
13 | |
12 | |
|
14 | namespace wasSharp.Collections.Specialized |
13 | namespace wasSharp.Collections.Specialized |
|
15 | { |
14 | { |
|
16 | public static class ConcurrentHashSetExtensions |
15 | public static class ConcurrentHashSetExtensions |
|
17 | { |
16 | { |
|
18 | public static ConcurrentHashSet<T> ToConcurrentHashSet<T>(this IEnumerable<T> enumerable) |
17 | public static ConcurrentHashSet<T> ToConcurrentHashSet<T>(this IEnumerable<T> enumerable) |
|
19 | { |
18 | { |
|
20 | return new ConcurrentHashSet<T>(enumerable); |
19 | return new ConcurrentHashSet<T>(enumerable); |
|
21 | } |
20 | } |
|
22 | } |
21 | } |
|
23 | |
22 | |
|
24 | public class ConcurrentHashSet<T> : IDisposable, ICollection<T>, IEnumerable<T>, ISet<T> |
23 | public class ConcurrentHashSet<T> : IDisposable, ISet<T> |
|
25 | { |
24 | { |
|
26 | private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
25 | private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
|
27 | private readonly HashSet<T> _hashSet = null; |
- | ||
28 | private IEnumerable<string> enumerable; |
26 | private readonly HashSet<T> _hashSet; |
|
29 | |
27 | |
|
30 | public ConcurrentHashSet() |
28 | public ConcurrentHashSet() |
|
31 | { |
29 | { |
|
32 | _lock.EnterWriteLock(); |
30 | _lock.EnterWriteLock(); |
|
33 | try |
31 | try |
|
34 | { |
32 | { |
|
35 | _hashSet = new HashSet<T>(); |
33 | _hashSet = new HashSet<T>(); |
|
36 | } |
34 | } |
|
37 | finally |
35 | finally |
|
38 | { |
36 | { |
|
39 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
37 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
40 | } |
38 | } |
|
41 | } |
39 | } |
|
42 | |
40 | |
|
43 | public ConcurrentHashSet(IEqualityComparer<T> stringComparer) |
41 | public ConcurrentHashSet(IEqualityComparer<T> stringComparer) |
|
44 | { |
42 | { |
|
45 | _lock.EnterWriteLock(); |
43 | _lock.EnterWriteLock(); |
|
46 | try |
44 | try |
|
47 | { |
45 | { |
|
48 | _hashSet = new HashSet<T>(stringComparer); |
46 | _hashSet = new HashSet<T>(stringComparer); |
|
49 | } |
47 | } |
|
50 | finally |
48 | finally |
|
51 | { |
49 | { |
|
52 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
50 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
53 | } |
51 | } |
|
54 | } |
52 | } |
|
55 | |
53 | |
|
56 | public ConcurrentHashSet(IEnumerable<T> enumerable) |
54 | public ConcurrentHashSet(IEnumerable<T> enumerable) |
|
57 | { |
55 | { |
|
58 | _lock.EnterWriteLock(); |
56 | _lock.EnterWriteLock(); |
|
59 | try |
57 | try |
|
60 | { |
58 | { |
|
61 | _hashSet = new HashSet<T>(); |
59 | _hashSet = new HashSet<T>(); |
|
62 | foreach (var i in enumerable) |
60 | foreach (var i in enumerable) |
|
63 | { |
61 | { |
|
64 | _hashSet.Add(i); |
62 | _hashSet.Add(i); |
|
65 | } |
63 | } |
|
66 | } |
64 | } |
|
67 | finally |
65 | finally |
|
68 | { |
66 | { |
|
69 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
67 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
70 | } |
68 | } |
|
71 | } |
69 | } |
|
72 | |
70 | |
|
73 | #region Implementation of ICollection<T> |
71 | #region Implementation of ICollection<T> |
|
74 | |
72 | |
|
75 | public bool Add(T item) |
73 | public bool Add(T item) |
|
76 | { |
74 | { |
|
77 | _lock.EnterWriteLock(); |
75 | _lock.EnterWriteLock(); |
|
78 | try |
76 | try |
|
79 | { |
77 | { |
|
80 | return _hashSet.Add(item); |
78 | return _hashSet.Add(item); |
|
81 | } |
79 | } |
|
82 | finally |
80 | finally |
|
83 | { |
81 | { |
|
84 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
82 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
85 | } |
83 | } |
|
86 | } |
84 | } |
|
87 | |
85 | |
|
88 | public void Clear() |
86 | public void Clear() |
|
89 | { |
87 | { |
|
90 | _lock.EnterWriteLock(); |
88 | _lock.EnterWriteLock(); |
|
91 | try |
89 | try |
|
92 | { |
90 | { |
|
93 | _hashSet.Clear(); |
91 | _hashSet.Clear(); |
|
94 | } |
92 | } |
|
95 | finally |
93 | finally |
|
96 | { |
94 | { |
|
97 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
95 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
98 | } |
96 | } |
|
99 | } |
97 | } |
|
100 | |
98 | |
|
101 | public bool Contains(T item) |
99 | public bool Contains(T item) |
|
102 | { |
100 | { |
|
103 | _lock.EnterReadLock(); |
101 | _lock.EnterReadLock(); |
|
104 | try |
102 | try |
|
105 | { |
103 | { |
|
106 | return _hashSet.Contains(item); |
104 | return _hashSet.Contains(item); |
|
107 | } |
105 | } |
|
108 | finally |
106 | finally |
|
109 | { |
107 | { |
|
110 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
108 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
111 | } |
109 | } |
|
112 | } |
110 | } |
|
113 | |
111 | |
|
114 | public bool Remove(T item) |
112 | public bool Remove(T item) |
|
115 | { |
113 | { |
|
116 | _lock.EnterWriteLock(); |
114 | _lock.EnterWriteLock(); |
|
117 | try |
115 | try |
|
118 | { |
116 | { |
|
119 | return _hashSet.Remove(item); |
117 | return _hashSet.Remove(item); |
|
120 | } |
118 | } |
|
121 | finally |
119 | finally |
|
122 | { |
120 | { |
|
123 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
121 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
124 | } |
122 | } |
|
125 | } |
123 | } |
|
126 | |
124 | |
|
127 | public int RemoveWhere(Predicate<T> match) |
125 | public int RemoveWhere(Predicate<T> match) |
|
128 | { |
126 | { |
|
129 | _lock.EnterWriteLock(); |
127 | _lock.EnterWriteLock(); |
|
130 | try |
128 | try |
|
131 | { |
129 | { |
|
132 | return _hashSet.RemoveWhere(match); |
130 | return _hashSet.RemoveWhere(match); |
|
133 | } |
131 | } |
|
134 | finally |
132 | finally |
|
135 | { |
133 | { |
|
136 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
134 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
137 | } |
135 | } |
|
138 | } |
136 | } |
|
139 | |
137 | |
|
140 | public int Count |
138 | public int Count |
|
141 | { |
139 | { |
|
142 | get |
140 | get |
|
143 | { |
141 | { |
|
144 | _lock.EnterReadLock(); |
142 | _lock.EnterReadLock(); |
|
145 | try |
143 | try |
|
146 | { |
144 | { |
|
147 | return _hashSet.Count; |
145 | return _hashSet.Count; |
|
148 | } |
146 | } |
|
149 | finally |
147 | finally |
|
150 | { |
148 | { |
|
151 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
149 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
152 | } |
150 | } |
|
153 | } |
151 | } |
|
154 | } |
152 | } |
|
155 | |
153 | |
|
156 | void ICollection<T>.Add(T item) |
154 | void ICollection<T>.Add(T item) |
|
157 | { |
155 | { |
|
158 | _lock.EnterWriteLock(); |
156 | _lock.EnterWriteLock(); |
|
159 | try |
157 | try |
|
160 | { |
158 | { |
|
161 | _hashSet.Add(item); |
159 | _hashSet.Add(item); |
|
162 | } |
160 | } |
|
163 | finally |
161 | finally |
|
164 | { |
162 | { |
|
165 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
163 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
166 | } |
164 | } |
|
167 | } |
165 | } |
|
168 | |
166 | |
|
169 | public void CopyTo(T[] array, int arrayIndex) |
167 | public void CopyTo(T[] array, int arrayIndex) |
|
170 | { |
168 | { |
|
171 | _lock.EnterReadLock(); |
169 | _lock.EnterReadLock(); |
|
172 | try |
170 | try |
|
173 | { |
171 | { |
|
174 | _hashSet.CopyTo(array, arrayIndex); |
172 | _hashSet.CopyTo(array, arrayIndex); |
|
175 | } |
173 | } |
|
176 | finally |
174 | finally |
|
177 | { |
175 | { |
|
178 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
176 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
179 | } |
177 | } |
|
180 | } |
178 | } |
|
181 | |
179 | |
|
182 | public IEnumerator<T> GetEnumerator() |
180 | public IEnumerator<T> GetEnumerator() |
|
183 | { |
181 | { |
|
184 | _lock.EnterReadLock(); |
182 | _lock.EnterReadLock(); |
|
185 | try |
183 | try |
|
186 | { |
184 | { |
|
187 | return _hashSet.GetEnumerator(); |
185 | using (var enumerator = _hashSet.GetEnumerator()) |
|
- | 186 | { |
||
- | 187 | while (enumerator.MoveNext()) |
||
- | 188 | yield return enumerator.Current; |
||
- | 189 | } |
||
188 | } |
190 | } |
|
189 | finally |
191 | finally |
|
190 | { |
192 | { |
|
191 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
193 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
192 | } |
194 | } |
|
193 | } |
195 | } |
|
194 | |
196 | |
|
195 | IEnumerator IEnumerable.GetEnumerator() |
197 | IEnumerator IEnumerable.GetEnumerator() |
|
196 | { |
198 | { |
|
197 | _lock.EnterReadLock(); |
199 | _lock.EnterReadLock(); |
|
198 | try |
200 | try |
|
199 | { |
201 | { |
|
200 | return _hashSet.GetEnumerator(); |
202 | using (var enumerator = _hashSet.GetEnumerator()) |
|
- | 203 | { |
||
- | 204 | while (enumerator.MoveNext()) |
||
- | 205 | yield return enumerator.Current; |
||
- | 206 | } |
||
201 | } |
207 | } |
|
202 | finally |
208 | finally |
|
203 | { |
209 | { |
|
204 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
210 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
205 | } |
211 | } |
|
206 | } |
212 | } |
|
207 | |
- | ||
208 | public bool IsReadOnly |
- | ||
209 | { |
- | ||
210 | get |
- | ||
211 | { |
213 | |
|
212 | return ((ICollection<T>)_hashSet).IsReadOnly; |
- | ||
213 | } |
- | ||
214 | } |
214 | public bool IsReadOnly => ((ICollection<T>)_hashSet).IsReadOnly; |
|
215 | |
215 | |
|
216 | #endregion Implementation of ICollection<T> |
216 | #endregion Implementation of ICollection<T> |
|
217 | |
217 | |
|
218 | #region Dispose |
218 | #region Dispose |
|
219 | |
219 | |
|
220 | public void Dispose() |
220 | public void Dispose() |
|
221 | { |
221 | { |
|
222 | Dispose(true); |
222 | Dispose(true); |
|
223 | GC.SuppressFinalize(this); |
223 | GC.SuppressFinalize(this); |
|
224 | } |
224 | } |
|
225 | |
225 | |
|
226 | protected virtual void Dispose(bool disposing) |
226 | protected virtual void Dispose(bool disposing) |
|
227 | { |
227 | { |
|
228 | if (disposing) |
228 | if (!disposing) return; |
|
229 | { |
- | ||
230 | if (_lock != null) |
- | ||
231 | _lock.Dispose(); |
229 | _lock?.Dispose(); |
|
232 | _hashSet.Clear(); |
230 | _hashSet.Clear(); |
|
233 | } |
- | ||
234 | } |
231 | } |
|
235 | |
232 | |
|
236 | ~ConcurrentHashSet() |
233 | ~ConcurrentHashSet() |
|
237 | { |
234 | { |
|
238 | Dispose(false); |
235 | Dispose(false); |
|
239 | } |
236 | } |
|
240 | |
237 | |
|
241 | #endregion Dispose |
238 | #endregion Dispose |
|
242 | |
239 | |
|
243 | #region Implementation of ISet<T> |
240 | #region Implementation of ISet<T> |
|
244 | |
241 | |
|
245 | public void ExceptWith(IEnumerable<T> other) |
242 | public void ExceptWith(IEnumerable<T> other) |
|
246 | { |
243 | { |
|
247 | _lock.EnterWriteLock(); |
244 | _lock.EnterWriteLock(); |
|
248 | try |
245 | try |
|
249 | { |
246 | { |
|
250 | _hashSet.ExceptWith(other); |
247 | _hashSet.ExceptWith(other); |
|
251 | } |
248 | } |
|
252 | finally |
249 | finally |
|
253 | { |
250 | { |
|
254 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
251 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
255 | } |
252 | } |
|
256 | } |
253 | } |
|
257 | |
254 | |
|
258 | public void IntersectWith(IEnumerable<T> other) |
255 | public void IntersectWith(IEnumerable<T> other) |
|
259 | { |
256 | { |
|
260 | _lock.EnterWriteLock(); |
257 | _lock.EnterWriteLock(); |
|
261 | try |
258 | try |
|
262 | { |
259 | { |
|
263 | _hashSet.IntersectWith(other); |
260 | _hashSet.IntersectWith(other); |
|
264 | } |
261 | } |
|
265 | finally |
262 | finally |
|
266 | { |
263 | { |
|
267 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
264 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
268 | } |
265 | } |
|
269 | } |
266 | } |
|
270 | |
267 | |
|
271 | public bool IsProperSubsetOf(IEnumerable<T> other) |
268 | public bool IsProperSubsetOf(IEnumerable<T> other) |
|
272 | { |
269 | { |
|
273 | _lock.EnterReadLock(); |
270 | _lock.EnterReadLock(); |
|
274 | try |
271 | try |
|
275 | { |
272 | { |
|
276 | return _hashSet.IsProperSubsetOf(other); |
273 | return _hashSet.IsProperSubsetOf(other); |
|
277 | } |
274 | } |
|
278 | finally |
275 | finally |
|
279 | { |
276 | { |
|
280 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
277 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
281 | } |
278 | } |
|
282 | } |
279 | } |
|
283 | |
280 | |
|
284 | public bool IsProperSupersetOf(IEnumerable<T> other) |
281 | public bool IsProperSupersetOf(IEnumerable<T> other) |
|
285 | { |
282 | { |
|
286 | _lock.EnterReadLock(); |
283 | _lock.EnterReadLock(); |
|
287 | try |
284 | try |
|
288 | { |
285 | { |
|
289 | return _hashSet.IsProperSupersetOf(other); |
286 | return _hashSet.IsProperSupersetOf(other); |
|
290 | } |
287 | } |
|
291 | finally |
288 | finally |
|
292 | { |
289 | { |
|
293 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
290 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
294 | } |
291 | } |
|
295 | } |
292 | } |
|
296 | |
293 | |
|
297 | public bool IsSubsetOf(IEnumerable<T> other) |
294 | public bool IsSubsetOf(IEnumerable<T> other) |
|
298 | { |
295 | { |
|
299 | _lock.EnterReadLock(); |
296 | _lock.EnterReadLock(); |
|
300 | try |
297 | try |
|
301 | { |
298 | { |
|
302 | return _hashSet.IsSubsetOf(other); |
299 | return _hashSet.IsSubsetOf(other); |
|
303 | } |
300 | } |
|
304 | finally |
301 | finally |
|
305 | { |
302 | { |
|
306 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
303 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
307 | } |
304 | } |
|
308 | } |
305 | } |
|
309 | |
306 | |
|
310 | public bool IsSupersetOf(IEnumerable<T> other) |
307 | public bool IsSupersetOf(IEnumerable<T> other) |
|
311 | { |
308 | { |
|
312 | _lock.EnterReadLock(); |
309 | _lock.EnterReadLock(); |
|
313 | try |
310 | try |
|
314 | { |
311 | { |
|
315 | return _hashSet.IsSupersetOf(other); |
312 | return _hashSet.IsSupersetOf(other); |
|
316 | } |
313 | } |
|
317 | finally |
314 | finally |
|
318 | { |
315 | { |
|
319 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
316 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
320 | } |
317 | } |
|
321 | } |
318 | } |
|
322 | |
319 | |
|
323 | public bool Overlaps(IEnumerable<T> other) |
320 | public bool Overlaps(IEnumerable<T> other) |
|
324 | { |
321 | { |
|
325 | _lock.EnterReadLock(); |
322 | _lock.EnterReadLock(); |
|
326 | try |
323 | try |
|
327 | { |
324 | { |
|
328 | return _hashSet.Overlaps(other); |
325 | return _hashSet.Overlaps(other); |
|
329 | } |
326 | } |
|
330 | finally |
327 | finally |
|
331 | { |
328 | { |
|
332 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
329 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
333 | } |
330 | } |
|
334 | } |
331 | } |
|
335 | |
332 | |
|
336 | public bool SetEquals(IEnumerable<T> other) |
333 | public bool SetEquals(IEnumerable<T> other) |
|
337 | { |
334 | { |
|
338 | _lock.EnterReadLock(); |
335 | _lock.EnterReadLock(); |
|
339 | try |
336 | try |
|
340 | { |
337 | { |
|
341 | return _hashSet.SetEquals(other); |
338 | return _hashSet.SetEquals(other); |
|
342 | } |
339 | } |
|
343 | finally |
340 | finally |
|
344 | { |
341 | { |
|
345 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
342 | if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
|
346 | } |
343 | } |
|
347 | } |
344 | } |
|
348 | |
345 | |
|
349 | public void SymmetricExceptWith(IEnumerable<T> other) |
346 | public void SymmetricExceptWith(IEnumerable<T> other) |
|
350 | { |
347 | { |
|
351 | _lock.EnterWriteLock(); |
348 | _lock.EnterWriteLock(); |
|
352 | try |
349 | try |
|
353 | { |
350 | { |
|
354 | _hashSet.SymmetricExceptWith(other); |
351 | _hashSet.SymmetricExceptWith(other); |
|
355 | } |
352 | } |
|
356 | finally |
353 | finally |
|
357 | { |
354 | { |
|
358 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
355 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
359 | } |
356 | } |
|
360 | } |
357 | } |
|
361 | |
358 | |
|
362 | public void UnionWith(IEnumerable<T> other) |
359 | public void UnionWith(IEnumerable<T> other) |
|
363 | { |
360 | { |
|
364 | _lock.EnterWriteLock(); |
361 | _lock.EnterWriteLock(); |
|
365 | try |
362 | try |
|
366 | { |
363 | { |
|
367 | _hashSet.UnionWith(other); |
364 | _hashSet.UnionWith(other); |
|
368 | } |
365 | } |
|
369 | finally |
366 | finally |
|
370 | { |
367 | { |
|
371 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
368 | if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
|
372 | } |
369 | } |
|
373 | } |
370 | } |
|
374 | |
371 | |
|
375 | #endregion Implementation of ISet<T> |
372 | #endregion Implementation of ISet<T> |
|
376 | } |
373 | } |
|
377 | } |
374 | } |
|
378 | |
375 | |