Files

431 lines
9.8 KiB
C#

#nullable enable
using System.Collections;
using System.Runtime.Serialization;
namespace Masuit.Tools.Abstractions.Systems
{
[Serializable]
public sealed class ConcurrentLinkedList<T> :
ICollection<T>,
IEnumerable<T>,
IEnumerable,
IReadOnlyCollection<T>,
ICollection,
IDeserializationCallback,
ISerializable,
IDisposable
{
private readonly ReaderWriterLockSlim _lock = new(LockRecursionPolicy.SupportsRecursion);
private readonly LinkedList<T> _linkedList;
#region Properties
public int Count
{
get
{
_lock.EnterReadLock();
try
{
return _linkedList.Count;
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
}
public bool IsSynchronized => false;
public object SyncRoot => false;
public bool IsReadOnly => false;
public LinkedListNode<T>? First
{
get
{
_lock.EnterReadLock();
try
{
return _linkedList.First;
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
}
public LinkedListNode<T>? Last
{
get
{
_lock.EnterReadLock();
try
{
return _linkedList.Last;
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
}
#endregion
#region Constructors
public ConcurrentLinkedList()
{
_linkedList = [];
}
public ConcurrentLinkedList(IEnumerable<T> collection)
{
_linkedList = new LinkedList<T>(collection);
}
public ConcurrentLinkedList(SerializationInfo info, StreamingContext context)
{
_linkedList = [];
ISerializable iSerializable = _linkedList;
iSerializable.GetObjectData(info, context);
}
#endregion
#region Add methods
public void Add(T item)
{
AddLast(item);
}
public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
_lock.EnterWriteLock();
try
{
_linkedList.AddAfter(node, newNode);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
{
_lock.EnterWriteLock();
try
{
return _linkedList.AddAfter(node, value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
_lock.EnterWriteLock();
try
{
_linkedList.AddBefore(node, newNode);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
{
_lock.EnterWriteLock();
try
{
return _linkedList.AddBefore(node, value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void AddFirst(LinkedListNode<T> node)
{
_lock.EnterWriteLock();
try
{
_linkedList.AddFirst(node);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T> AddFirst(T value)
{
_lock.EnterWriteLock();
try
{
return _linkedList.AddFirst(value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void AddLast(LinkedListNode<T> node)
{
_lock.EnterWriteLock();
try
{
_linkedList.AddLast(node);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T> AddLast(T value)
{
_lock.EnterWriteLock();
try
{
return _linkedList.AddLast(value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
#endregion
#region List Operations
public void Clear()
{
_lock.EnterWriteLock();
try
{
_linkedList.Clear();
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public bool Contains(T item)
{
_lock.EnterReadLock();
try
{
return _linkedList.Contains(item);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void CopyTo(T[] array, int arrayIndex)
{
_lock.EnterReadLock();
try
{
_linkedList.CopyTo(array, arrayIndex);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void CopyTo(Array array, int index)
{
_lock.EnterReadLock();
try
{
((ICollection)_linkedList).CopyTo(array, index);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T>? Find(T value)
{
_lock.EnterReadLock();
try
{
return _linkedList.Find(value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public LinkedListNode<T>? FindLast(T value)
{
_lock.EnterReadLock();
try
{
return _linkedList.FindLast(value);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
_lock.EnterReadLock();
try
{
_linkedList.GetObjectData(info, context);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void OnDeserialization(object? sender)
{
_linkedList.OnDeserialization(sender);
}
public IEnumerator<T> GetEnumerator()
{
List<T> snapshot;
_lock.EnterReadLock();
try
{
snapshot = _linkedList.ToList();
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
return snapshot.GetEnumerator();
}
#endregion
#region Remove methods
public void Remove(LinkedListNode<T> node)
{
_lock.EnterWriteLock();
try
{
_linkedList.Remove(node);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public bool Remove(T item)
{
_lock.EnterWriteLock();
try
{
return _linkedList.Remove(item);
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void RemoveFirst()
{
_lock.EnterWriteLock();
try
{
_linkedList.RemoveFirst();
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
public void RemoveLast()
{
_lock.EnterWriteLock();
try
{
_linkedList.RemoveLast();
}
finally
{
if (_lock.IsReadLockHeld)
_lock.ExitReadLock();
}
}
#endregion
#region Dispose
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (disposing)
_lock.Dispose();
}
~ConcurrentLinkedList()
{
Dispose(false);
}
#endregion
}
}