wasSharp – Rev 44
?pathlinks?
///////////////////////////////////////////////////////////////////////////
// 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 static class ConcurrentHashSetExtensions
{
public static ConcurrentHashSet<T> ToConcurrentHashSet<T>(this IEnumerable<T> enumerable)
{
return new ConcurrentHashSet<T>(enumerable);
}
}
public class ConcurrentHashSet<T> : IDisposable, ISet<T>
{
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
private readonly HashSet<T> _hashSet;
public ConcurrentHashSet()
{
_lock.EnterWriteLock();
try
{
_hashSet = new HashSet<T>();
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public ConcurrentHashSet(IEqualityComparer<T> stringComparer)
{
_lock.EnterWriteLock();
try
{
_hashSet = new HashSet<T>(stringComparer);
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
public ConcurrentHashSet(IEnumerable<T> enumerable)
{
_lock.EnterWriteLock();
try
{
_hashSet = new HashSet<T>();
foreach (var i in enumerable)
{
_hashSet.Add(i);
}
}
finally
{
if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
}
}
#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 RemoveWhere(Predicate<T> match)
{
_lock.EnterWriteLock();
try
{
return _hashSet.RemoveWhere(match);
}
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
{
using (var enumerator = _hashSet.GetEnumerator())
{
while (enumerator.MoveNext())
yield return enumerator.Current;
}
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
_lock.EnterReadLock();
try
{
using (var enumerator = _hashSet.GetEnumerator())
{
while (enumerator.MoveNext())
yield return enumerator.Current;
}
}
finally
{
if (_lock.IsReadLockHeld) _lock.ExitReadLock();
}
}
public bool IsReadOnly => ((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) return;
_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>
}
}