// WingsEmu
//
// Developed by NosWings Team
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace WingsEmu.Core.Generics;
///
/// This class is used to store key-value based items in a thread safe manner. It uses
/// publicly.
///
/// Key type
/// Value type
public class ThreadSafeSortedList : IDisposable
{
#region Instantiation
///
/// Creates a new ThreadSafeSortedList object.
///
public ThreadSafeSortedList()
{
_items = new SortedList();
_lock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
}
#endregion
#region Properties
///
/// Gets count of items in the collection.
///
public int Count
{
get
{
if (_disposed)
{
return 0;
}
_lock.EnterReadLock();
try
{
return _items.Count;
}
finally
{
_lock.ExitReadLock();
}
return 0;
}
}
#endregion
#region Indexers
///
/// Gets/adds/replaces an item by key.
///
/// Key to get/set value
/// Item associated with this key
public TV this[TK key]
{
get
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.ContainsKey(key) ? _items[key] : default;
}
finally
{
_lock.ExitReadLock();
}
}
set
{
if (_disposed)
{
return;
}
_lock.EnterWriteLock();
try
{
_items[key] = value;
}
finally
{
_lock.ExitWriteLock();
}
}
}
#endregion
#region Members
///
/// private collection to store _items.
///
private readonly SortedList _items;
///
/// Used to synchronize access to _items list.
///
private readonly ReaderWriterLockSlim _lock;
private bool _disposed;
#endregion
#region Methods
///
/// Determines whether all elements of a sequence satisfy a condition.
///
///
/// True; if elements satisfy the condition
public bool All(Func predicate)
{
if (_disposed)
{
return false;
}
_lock.EnterReadLock();
try
{
return _items.Values.All(predicate);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Determines whether any element of a sequence satisfies a condition.
///
///
///
///
///
public bool Any(Func predicate)
{
if (_disposed)
{
return false;
}
_lock.EnterReadLock();
try
{
return _items.Values.Any(predicate);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Removes all items from list.
///
public void ClearAll()
{
if (_disposed)
{
return;
}
_lock.EnterWriteLock();
try
{
_items.Clear();
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// Checks if collection contains spesified key.
///
/// Key to check
/// True; if collection contains given key
public bool ContainsKey(TK key)
{
if (_disposed)
{
return false;
}
_lock.EnterReadLock();
try
{
return _items.ContainsKey(key);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Checks if collection contains spesified item.
///
/// Item to check
/// True; if collection contains given item
public bool ContainsValue(TV item)
{
if (_disposed)
{
return false;
}
_lock.EnterReadLock();
try
{
return _items.ContainsValue(item);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// number of found elements
public int CountLinq(Func predicate)
{
if (_disposed)
{
return 0;
}
_lock.EnterReadLock();
try
{
return _items.Values.Count(predicate);
}
finally
{
_lock.ExitReadLock();
}
return 0;
}
///
/// Disposes the current object.
///
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Returns the first element of the sequence that satisfies a condition or a default value
/// if no such element is found.
///
///
/// object
public TV FirstOrDefault(Func predicate)
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.FirstOrDefault(predicate);
}
finally
{
_lock.ExitReadLock();
}
return default;
}
///
/// Performs the specified action on each element of the .
///
///
public void ForEach(Action action)
{
if (_disposed)
{
return;
}
_lock.EnterReadLock();
try
{
_items.Values.ToList().ForEach(action);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Gets all items in collection.
///
///
///
///
public List GetAllItems()
{
if (_disposed)
{
return new List();
}
_lock.EnterReadLock();
try
{
return new List(_items.Values);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Gets then removes all items in collection.
///
///
///
///
public List GetAndClearAllItems()
{
if (_disposed)
{
return new List();
}
_lock.EnterWriteLock();
try
{
var list = new List(_items.Values);
_items.Clear();
return list;
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// Returns the last element of a sequence that satisfies a specified condition.
///
///
/// object
public TV Last(Func predicate)
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.Last(predicate);
}
finally
{
_lock.ExitReadLock();
}
return default;
}
///
/// Returns the last element of a sequence.
///
/// object
public TV Last()
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.Last();
}
finally
{
_lock.ExitReadLock();
}
return default;
}
///
/// Returns the last element of a sequence that satisfies a condition or a default value if
/// no such element is found.
///
///
/// object
public TV LastOrDefault(Func predicate)
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.LastOrDefault(predicate);
}
finally
{
_lock.ExitReadLock();
}
return default;
}
///
/// Returns the last element of a sequence, or a default value if the sequence contains no elements.
///
/// object
public TV LastOrDefault()
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.LastOrDefault();
}
finally
{
_lock.ExitReadLock();
}
return default;
}
///
/// Removes an item from collection.
///
/// Key of item to remove
/// if removed
public bool Remove(TK key)
{
if (_disposed)
{
return false;
}
_lock.EnterWriteLock();
try
{
if (!_items.ContainsKey(key))
{
return false;
}
_items.Remove(key);
return true;
}
finally
{
_lock.ExitWriteLock();
}
}
///
/// Removes an item from collection.
///
/// Value of item to remove
/// if removed
public bool Remove(TV value)
{
if (_disposed)
{
return false;
}
_lock.EnterWriteLock();
try
{
if (!_items.ContainsValue(value))
{
return false;
}
_items.RemoveAt(_items.IndexOfValue(value));
return true;
}
finally
{
_lock.ExitWriteLock();
}
return false;
}
///
/// Projects each element of a sequence into a new form.
///
///
///
public IEnumerable Select(Func selector)
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.Select(selector);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Returns the only element of a sequence that satisfies a specified condition, and throws
/// an exception if more than one such element exists.
///
///
/// object
public TV Single(Func predicate)
{
if (_disposed)
{
return default;
}
_lock.EnterReadLock();
try
{
return _items.Values.Single(predicate);
}
finally
{
_lock.ExitReadLock();
}
}
///
/// Returns the only element of a sequence that satisfies a specified condition or a default
/// value if no such element exists; this method throws an exception if more than one element
/// satisfies the condition.
///
///
/// object
public TV SingleOrDefault(Func predicate)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.SingleOrDefault(predicate);
}
finally
{
_lock.ExitReadLock();
}
}
return default;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// number of found elements
public int Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// int? number of found elements
public int? Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// number of found elements
public long Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// long? number of found elements
public long? Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// number of found elements
public double Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Returns a number that represents how many elements in the specified sequence satisfy a condition.
///
///
/// double? number of found elements
public double? Sum(Func selector)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return _items.Values.Sum(selector);
}
finally
{
_lock.ExitReadLock();
}
}
return 0;
}
///
/// Filters a sequence of values based on a predicate.
///
///
///
///
///
public List Where(Func predicate)
{
if (!_disposed)
{
_lock.EnterReadLock();
try
{
return new List(_items.Values.Where(predicate));
}
finally
{
_lock.ExitReadLock();
}
}
return new List();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
ClearAll();
_lock.Dispose();
}
}
#endregion
}