1
0
mirror of https://github.com/chylex/Minecraft-Phantom-Panel.git synced 2025-08-21 15:54:06 +02:00
Files
.config
.run
.workdir
Agent
Common
Docker
Server
Utils
Phantom.Utils.Collections
Phantom.Utils.Collections.csproj
RingBuffer.cs
RwLockedDictionary.cs
Table.cs
Phantom.Utils.Collections.Tests
Phantom.Utils.Cryptography
Phantom.Utils.Events
Phantom.Utils.IO
Phantom.Utils.Rpc
Phantom.Utils.Runtime
Phantom.Utils.Runtime.Tests
.gitattributes
.gitignore
AddMigration.bat
AddMigration.sh
PhantomPanel.sln
global.json

183 lines
4.0 KiB
C#

using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
namespace Phantom.Utils.Collections;
public sealed class RwLockedDictionary<TKey, TValue> where TKey : notnull {
private readonly Dictionary<TKey, TValue> dict;
private readonly ReaderWriterLockSlim rwLock;
public RwLockedDictionary(LockRecursionPolicy recursionPolicy) {
this.dict = new Dictionary<TKey, TValue>();
this.rwLock = new ReaderWriterLockSlim(recursionPolicy);
}
public RwLockedDictionary(int capacity, LockRecursionPolicy recursionPolicy) {
this.dict = new Dictionary<TKey, TValue>(capacity);
this.rwLock = new ReaderWriterLockSlim(recursionPolicy);
}
public TValue this[TKey key] {
get {
rwLock.EnterReadLock();
try {
return dict[key];
} finally {
rwLock.ExitReadLock();
}
}
set {
rwLock.EnterWriteLock();
try {
dict[key] = value;
} finally {
rwLock.ExitWriteLock();
}
}
}
public ImmutableArray<TValue> ValuesCopy {
get {
rwLock.EnterReadLock();
try {
return dict.Values.ToImmutableArray();
} finally {
rwLock.ExitReadLock();
}
}
}
public void ForEachValue(Action<TValue> action) {
rwLock.EnterReadLock();
try {
foreach (var value in dict.Values) {
action(value);
}
} finally {
rwLock.ExitReadLock();
}
}
public bool AddOrReplace(TKey key, TValue newValue, [MaybeNullWhen(false)] out TValue oldValue) {
rwLock.EnterWriteLock();
try {
bool hadValue = dict.TryGetValue(key, out oldValue);
dict[key] = newValue;
return hadValue;
} finally {
rwLock.ExitWriteLock();
}
}
public bool Remove(TKey key) {
rwLock.EnterWriteLock();
try {
return dict.Remove(key);
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryGetValue(TKey key, [MaybeNullWhen(false)] out TValue value) {
rwLock.EnterReadLock();
try {
return dict.TryGetValue(key, out value);
} finally {
rwLock.ExitReadLock();
}
}
public bool TryAdd(TKey key, TValue newValue) {
rwLock.EnterWriteLock();
try {
return dict.TryAdd(key, newValue);
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryAddOrReplace(TKey key, TValue newValue, Predicate<TValue> replaceCondition) {
rwLock.EnterWriteLock();
try {
if (!dict.TryGetValue(key, out var oldValue) || replaceCondition(oldValue)) {
dict[key] = newValue;
return true;
}
else {
return false;
}
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryReplace(TKey key, Func<TValue, TValue> replacementValue) {
return TryReplaceIf(key, replacementValue, static _ => true);
}
public bool TryReplaceIf(TKey key, Func<TValue, TValue> replacementValue, Predicate<TValue> replaceCondition) {
rwLock.EnterWriteLock();
try {
if (dict.TryGetValue(key, out var oldValue) && replaceCondition(oldValue)) {
dict[key] = replacementValue(oldValue);
return true;
}
else {
return false;
}
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryReplaceAll(Func<TValue, TValue> replacementValue) {
return TryReplaceAllIf(replacementValue, static _ => true);
}
public bool TryReplaceAllIf(Func<TValue, TValue> replacementValue, Predicate<TValue> replaceCondition) {
rwLock.EnterWriteLock();
try {
bool hasChanged = false;
foreach (var (key, oldValue) in dict) {
if (replaceCondition(oldValue)) {
dict[key] = replacementValue(oldValue);
hasChanged = true;
}
}
return hasChanged;
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryRemove(TKey key) {
rwLock.EnterWriteLock();
try {
return dict.Remove(key);
} finally {
rwLock.ExitWriteLock();
}
}
public bool TryRemoveIf(TKey key, Predicate<TValue> removeCondition) {
rwLock.EnterWriteLock();
try {
return dict.TryGetValue(key, out var oldValue) && removeCondition(oldValue) && dict.Remove(key);
} finally {
rwLock.ExitWriteLock();
}
}
public ImmutableDictionary<TKey, TValue> ToImmutable() {
rwLock.EnterReadLock();
try {
return dict.ToImmutableDictionary();
} finally {
rwLock.ExitReadLock();
}
}
}