// 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 }