mirror of
https://github.com/JustArchiNET/ArchiSteamFarm.git
synced 2026-01-01 06:00:46 +00:00
Good idea
This commit is contained in:
@@ -46,6 +46,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
}
|
||||
|
||||
public bool Add(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
if (!BackingCollection.TryAdd(item, true)) {
|
||||
return false;
|
||||
}
|
||||
@@ -65,9 +67,18 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
OnModified?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public bool Contains(T item) => BackingCollection.ContainsKey(item);
|
||||
public bool Contains(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex) => BackingCollection.Keys.CopyTo(array, arrayIndex);
|
||||
return BackingCollection.ContainsKey(item);
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex) {
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex);
|
||||
|
||||
BackingCollection.Keys.CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public void ExceptWith(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
@@ -80,6 +91,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
public IEnumerator<T> GetEnumerator() => BackingCollection.Keys.GetEnumerator();
|
||||
|
||||
public void IntersectWith(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
foreach (T item in this.Where(item => !otherSet.Contains(item))) {
|
||||
@@ -88,36 +101,48 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
}
|
||||
|
||||
public bool IsProperSubsetOf(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count > Count) && IsSubsetOf(otherSet);
|
||||
}
|
||||
|
||||
public bool IsProperSupersetOf(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count < Count) && IsSupersetOf(otherSet);
|
||||
}
|
||||
|
||||
public bool IsSubsetOf(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return this.All(otherSet.Contains);
|
||||
}
|
||||
|
||||
public bool IsSupersetOf(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return otherSet.All(Contains);
|
||||
}
|
||||
|
||||
public bool Overlaps(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return otherSet.Any(Contains);
|
||||
}
|
||||
|
||||
public bool Remove(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
if (!BackingCollection.TryRemove(item, out _)) {
|
||||
return false;
|
||||
}
|
||||
@@ -128,12 +153,16 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
}
|
||||
|
||||
public bool SetEquals(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
|
||||
return (otherSet.Count == Count) && otherSet.All(Contains);
|
||||
}
|
||||
|
||||
public void SymmetricExceptWith(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
ISet<T> otherSet = other as ISet<T> ?? other.ToHashSet();
|
||||
HashSet<T> removed = [];
|
||||
|
||||
@@ -155,12 +184,18 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
}
|
||||
}
|
||||
|
||||
void ICollection<T>.Add(T item) => Add(item);
|
||||
void ICollection<T>.Add(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
Add(item);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
[PublicAPI]
|
||||
public bool AddRange(IEnumerable<T> items) {
|
||||
ArgumentNullException.ThrowIfNull(items);
|
||||
|
||||
bool result = false;
|
||||
|
||||
foreach (T _ in items.Where(Add)) {
|
||||
@@ -172,6 +207,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
|
||||
[PublicAPI]
|
||||
public bool RemoveRange(IEnumerable<T> items) {
|
||||
ArgumentNullException.ThrowIfNull(items);
|
||||
|
||||
bool result = false;
|
||||
|
||||
foreach (T _ in items.Where(Remove)) {
|
||||
@@ -182,10 +219,16 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public int RemoveWhere(Predicate<T> match) => BackingCollection.Keys.Where(match.Invoke).Count(key => BackingCollection.TryRemove(key, out _));
|
||||
public int RemoveWhere(Predicate<T> match) {
|
||||
ArgumentNullException.ThrowIfNull(match);
|
||||
|
||||
return BackingCollection.Keys.Where(match.Invoke).Count(key => BackingCollection.TryRemove(key, out _));
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public bool ReplaceIfNeededWith(IReadOnlyCollection<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
if (SetEquals(other)) {
|
||||
return false;
|
||||
}
|
||||
@@ -197,6 +240,8 @@ public sealed class ConcurrentHashSet<T> : IReadOnlySet<T>, ISet<T> where T : no
|
||||
|
||||
[PublicAPI]
|
||||
public void ReplaceWith(IEnumerable<T> other) {
|
||||
ArgumentNullException.ThrowIfNull(other);
|
||||
|
||||
Clear();
|
||||
UnionWith(other);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ using Nito.AsyncEx;
|
||||
|
||||
namespace ArchiSteamFarm.Collections;
|
||||
|
||||
public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> where T : notnull {
|
||||
[PublicAPI]
|
||||
public event EventHandler? OnModified;
|
||||
|
||||
@@ -55,6 +55,8 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
}
|
||||
|
||||
set {
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
BackingCollection[index] = value;
|
||||
}
|
||||
@@ -64,6 +66,8 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
}
|
||||
|
||||
public void Add(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
BackingCollection.Add(item);
|
||||
}
|
||||
@@ -80,12 +84,17 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
}
|
||||
|
||||
public bool Contains(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
using (Lock.ReaderLock()) {
|
||||
return BackingCollection.Contains(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex) {
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex);
|
||||
|
||||
using (Lock.ReaderLock()) {
|
||||
BackingCollection.CopyTo(array, arrayIndex);
|
||||
}
|
||||
@@ -94,12 +103,17 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
public IEnumerator<T> GetEnumerator() => new ConcurrentEnumerator<T>(BackingCollection, Lock.ReaderLock());
|
||||
|
||||
public int IndexOf(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
using (Lock.ReaderLock()) {
|
||||
return BackingCollection.IndexOf(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Insert(int index, T item) {
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(index);
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
BackingCollection.Insert(index, item);
|
||||
}
|
||||
@@ -108,6 +122,8 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
}
|
||||
|
||||
public bool Remove(T item) {
|
||||
ArgumentNullException.ThrowIfNull(item);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
if (!BackingCollection.Remove(item)) {
|
||||
return false;
|
||||
@@ -120,6 +136,8 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
}
|
||||
|
||||
public void RemoveAt(int index) {
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(index);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
BackingCollection.RemoveAt(index);
|
||||
}
|
||||
@@ -130,6 +148,8 @@ public sealed class ConcurrentList<T> : IList<T>, IReadOnlyList<T> {
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
internal void ReplaceWith(IEnumerable<T> collection) {
|
||||
ArgumentNullException.ThrowIfNull(collection);
|
||||
|
||||
using (Lock.WriterLock()) {
|
||||
BackingCollection.Clear();
|
||||
BackingCollection.AddRange(collection);
|
||||
|
||||
@@ -23,22 +23,17 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using ArchiSteamFarm.Core;
|
||||
|
||||
namespace ArchiSteamFarm.Collections;
|
||||
|
||||
internal sealed class FixedSizeConcurrentQueue<T> : IEnumerable<T> {
|
||||
internal sealed class FixedSizeConcurrentQueue<T> : IEnumerable<T> where T : notnull {
|
||||
private readonly ConcurrentQueue<T> BackingQueue = new();
|
||||
|
||||
internal byte MaxCount {
|
||||
get => BackingMaxCount;
|
||||
|
||||
set {
|
||||
if (value == 0) {
|
||||
ASF.ArchiLogger.LogNullError(value);
|
||||
|
||||
return;
|
||||
}
|
||||
ArgumentOutOfRangeException.ThrowIfZero(value);
|
||||
|
||||
BackingMaxCount = value;
|
||||
|
||||
@@ -58,6 +53,8 @@ internal sealed class FixedSizeConcurrentQueue<T> : IEnumerable<T> {
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
|
||||
internal void Enqueue(T obj) {
|
||||
ArgumentNullException.ThrowIfNull(obj);
|
||||
|
||||
BackingQueue.Enqueue(obj);
|
||||
|
||||
Resize();
|
||||
|
||||
@@ -54,6 +54,8 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
get => BackingDictionary[key];
|
||||
|
||||
set {
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
if (BackingDictionary.TryGetValue(key, out TValue? savedValue) && EqualityComparer<TValue>.Default.Equals(savedValue, value)) {
|
||||
return;
|
||||
}
|
||||
@@ -69,7 +71,11 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
Add(key, value);
|
||||
}
|
||||
|
||||
public void Add(TKey key, TValue value) => TryAdd(key, value);
|
||||
public void Add(TKey key, TValue value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
TryAdd(key, value);
|
||||
}
|
||||
|
||||
public void Clear() {
|
||||
if (BackingDictionary.IsEmpty) {
|
||||
@@ -81,7 +87,14 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<TKey, TValue> item) => ((ICollection<KeyValuePair<TKey, TValue>>) BackingDictionary).Contains(item);
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) => ((ICollection<KeyValuePair<TKey, TValue>>) BackingDictionary).CopyTo(array, arrayIndex);
|
||||
|
||||
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) {
|
||||
ArgumentNullException.ThrowIfNull(array);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(arrayIndex);
|
||||
|
||||
((ICollection<KeyValuePair<TKey, TValue>>) BackingDictionary).CopyTo(array, arrayIndex);
|
||||
}
|
||||
|
||||
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => BackingDictionary.GetEnumerator();
|
||||
|
||||
public bool Remove(KeyValuePair<TKey, TValue> item) {
|
||||
@@ -97,6 +110,8 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
}
|
||||
|
||||
public bool Remove(TKey key) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
if (!BackingDictionary.TryRemove(key, out _)) {
|
||||
return false;
|
||||
}
|
||||
@@ -106,14 +121,36 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IDictionary<TKey, TValue>.ContainsKey(TKey key) => BackingDictionary.ContainsKey(key);
|
||||
bool IReadOnlyDictionary<TKey, TValue>.ContainsKey(TKey key) => BackingDictionary.ContainsKey(key);
|
||||
bool IDictionary<TKey, TValue>.ContainsKey(TKey key) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
return BackingDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
bool IReadOnlyDictionary<TKey, TValue>.ContainsKey(TKey key) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
return BackingDictionary.ContainsKey(key);
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
bool IReadOnlyDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value) => BackingDictionary.TryGetValue(key, out value!);
|
||||
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value) => BackingDictionary.TryGetValue(key, out value!);
|
||||
|
||||
bool IReadOnlyDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
return BackingDictionary.TryGetValue(key, out value!);
|
||||
}
|
||||
|
||||
bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
return BackingDictionary.TryGetValue(key, out value!);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public bool TryAdd(TKey key, TValue value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
if (!BackingDictionary.TryAdd(key, value)) {
|
||||
return false;
|
||||
}
|
||||
@@ -124,5 +161,9 @@ public sealed class ObservableConcurrentDictionary<TKey, TValue> : IDictionary<T
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public bool TryGetValue(TKey key, out TValue? value) => BackingDictionary.TryGetValue(key, out value);
|
||||
public bool TryGetValue(TKey key, out TValue? value) {
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
return BackingDictionary.TryGetValue(key, out value);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user