using System; using System.Collections; using System.Collections.Generic; using System.Runtime.Serialization; using System.Threading; namespace Masuit.Tools.Systems; /// /// 并发HashSet /// /// public sealed class ConcurrentHashSet : ISet, IDisposable { private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.SupportsRecursion); private readonly HashSet _hashSet = new(); public int Count { get { _lock.EnterWriteLock(); try { return _hashSet.Count; } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } } public bool IsReadOnly => false; public ConcurrentHashSet() { } public ConcurrentHashSet(IEqualityComparer comparer) { _hashSet = new HashSet(comparer); } public ConcurrentHashSet(IEnumerable collection) { _hashSet = new HashSet(collection); } public ConcurrentHashSet(IEnumerable collection, IEqualityComparer comparer) { _hashSet = new HashSet(collection, comparer); } public ConcurrentHashSet(SerializationInfo info, StreamingContext context) { _hashSet = new HashSet(); var iSerializable = (ISerializable)_hashSet; iSerializable.GetObjectData(info, context); } public void OnDeserialization(object sender) { _hashSet.OnDeserialization(sender); } public void GetObjectData(SerializationInfo info, StreamingContext context) { _hashSet.GetObjectData(info, context); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { return _hashSet.GetEnumerator(); } public void Add(T item) { _lock.EnterWriteLock(); try { _hashSet.Add(item); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public void UnionWith(IEnumerable other) { _lock.EnterWriteLock(); _lock.EnterReadLock(); try { _hashSet.UnionWith(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } if (_lock.IsReadLockHeld) { _lock.ExitReadLock(); } } } public void IntersectWith(IEnumerable other) { _lock.EnterWriteLock(); _lock.EnterReadLock(); try { _hashSet.IntersectWith(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } if (_lock.IsReadLockHeld) { _lock.ExitReadLock(); } } } public void ExceptWith(IEnumerable other) { _lock.EnterWriteLock(); _lock.EnterReadLock(); try { _hashSet.ExceptWith(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } if (_lock.IsReadLockHeld) { _lock.ExitReadLock(); } } } public void SymmetricExceptWith(IEnumerable other) { _lock.EnterWriteLock(); try { _hashSet.SymmetricExceptWith(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool IsSubsetOf(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.IsSubsetOf(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool IsSupersetOf(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.IsSupersetOf(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool IsProperSupersetOf(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.IsProperSupersetOf(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool IsProperSubsetOf(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.IsProperSubsetOf(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool Overlaps(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.Overlaps(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool SetEquals(IEnumerable other) { _lock.EnterWriteLock(); try { return _hashSet.SetEquals(other); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } bool ISet.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.EnterWriteLock(); try { return _hashSet.Contains(item); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public void CopyTo(T[] array, int arrayIndex) { _lock.EnterWriteLock(); try { _hashSet.CopyTo(array, arrayIndex); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public bool Remove(T item) { _lock.EnterWriteLock(); try { return _hashSet.Remove(item); } finally { if (_lock.IsWriteLockHeld) { _lock.ExitWriteLock(); } } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (disposing && _lock != null) { _lock.Dispose(); } } ~ConcurrentHashSet() { Dispose(false); } }