/Collections/Specialized/ConcurrentHashSet.cs |
@@ -0,0 +1,311 @@ |
/////////////////////////////////////////////////////////////////////////// |
// Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // |
// Please see: http://www.gnu.org/licenses/gpl.html for legal details, // |
// rights of fair usage, the disclaimer and warranty conditions. // |
/////////////////////////////////////////////////////////////////////////// |
// Based on work by Ben Mosher |
|
using System; |
using System.Collections; |
using System.Collections.Generic; |
using System.Threading; |
|
namespace wasSharp.Collections.Specialized |
{ |
public class ConcurrentHashSet<T> : IDisposable, ICollection<T>, IEnumerable<T>, ISet<T> |
{ |
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); |
private readonly HashSet<T> _hashSet = new HashSet<T>(); |
|
#region Implementation of ICollection<T> |
|
public bool Add(T item) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
return _hashSet.Add(item); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public void Clear() |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.Clear(); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public bool Contains(T item) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.Contains(item); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool Remove(T item) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
return _hashSet.Remove(item); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public int Count |
{ |
get |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.Count; |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
} |
|
void ICollection<T>.Add(T item) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.Add(item); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public void CopyTo(T[] array, int arrayIndex) |
{ |
_lock.EnterReadLock(); |
try |
{ |
_hashSet.CopyTo(array, arrayIndex); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public IEnumerator<T> GetEnumerator() |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.GetEnumerator(); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
IEnumerator IEnumerable.GetEnumerator() |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.GetEnumerator(); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool IsReadOnly |
{ |
get |
{ |
return ((ICollection<T>)_hashSet).IsReadOnly; |
} |
} |
|
#endregion Implementation of ICollection<T> |
|
#region Dispose |
|
public void Dispose() |
{ |
Dispose(true); |
GC.SuppressFinalize(this); |
} |
|
protected virtual void Dispose(bool disposing) |
{ |
if (disposing) |
{ |
if (_lock != null) |
_lock.Dispose(); |
_hashSet.Clear(); |
} |
} |
|
~ConcurrentHashSet() |
{ |
Dispose(false); |
} |
|
#endregion Dispose |
|
#region Implementation of ISet<T> |
|
public void ExceptWith(IEnumerable<T> other) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.ExceptWith(other); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public void IntersectWith(IEnumerable<T> other) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.IntersectWith(other); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public bool IsProperSubsetOf(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.IsProperSubsetOf(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool IsProperSupersetOf(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.IsProperSupersetOf(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool IsSubsetOf(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.IsSubsetOf(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool IsSupersetOf(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.IsSupersetOf(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool Overlaps(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.Overlaps(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public bool SetEquals(IEnumerable<T> other) |
{ |
_lock.EnterReadLock(); |
try |
{ |
return _hashSet.SetEquals(other); |
} |
finally |
{ |
if (_lock.IsReadLockHeld) _lock.ExitReadLock(); |
} |
} |
|
public void SymmetricExceptWith(IEnumerable<T> other) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.SymmetricExceptWith(other); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
public void UnionWith(IEnumerable<T> other) |
{ |
_lock.EnterWriteLock(); |
try |
{ |
_hashSet.UnionWith(other); |
} |
finally |
{ |
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); |
} |
} |
|
#endregion Implementation of ISet<T> |
} |
} |