/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// // Based on the work of Herman Schoenfeld using System.Collections.Generic; using System.Linq; using System.Threading; namespace wasSharp.Collections.Specialized { public class ConcurrentMultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2] { get { _lock.EnterReadLock(); try { if (!ContainsKey(key1) || !this[key1].ContainsKey(key2)) { return default(V); } return base[key1][key2]; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new Dictionary(); this[key1][key2] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public new IEnumerable Values { get { _lock.EnterReadLock(); try { return base.Values.SelectMany(baseDict => baseDict.Keys, (baseDict, baseKey) => baseDict[baseKey]); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public void Add(K1 key1, K2 key2, V value) { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new Dictionary(); this[key1][key2] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public void Remove(K1 key1, K2 key2) { _lock.EnterWriteLock(); try { if (!ContainsKey(key1) || !this[key1].ContainsKey(key2)) { return; } this[key1].Remove(key2); Remove(key1); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public bool ContainsKey(K1 key1, K2 key2) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } public bool TryGetValue(K1 key1, K2 key2, out V value) { _lock.EnterReadLock(); try { if (!ContainsKey(key1) || !this[key1].ContainsKey(key2)) { value = default(V); return false; } value = base[key1][key2]; return true; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new ConcurrentMultiKeyDictionary(); this[key1][key2, key3] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } public void Add(K1 key1, K2 key2, K3 key3, V value) { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new ConcurrentMultiKeyDictionary(); this[key1][key2, key3] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public void Remove(K1 key1, K2 key2, K3 key3) { _lock.EnterWriteLock(); try { if (!ContainsKey(key1) || !this[key1].ContainsKey(key2, key3)) { return; } this[key1][key2].Remove(key3); this[key1].Remove(key2); Remove(key1); } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } public bool TryGetValue(K1 key1, K2 key2, K3 key3, out V value) { _lock.EnterReadLock(); try { if (!ContainsKey(key1) || !this[key1].ContainsKey(key2, key3)) { value = default(V); return false; } value = base[key1][key2, key3]; return true; } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6, key7] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6, key7] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6, key7); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6, key7, key8] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6, key7, key8] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6, key7, key8); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6, key7, key8, key9] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6, key7, key8, key9] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6, key7, key8, key9); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9, K10 key10] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6, key7, key8, key9, key10] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6, key7, key8, key9, key10] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9, K10 key10) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6, key7, key8, key9, key10); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } public class MultiKeyDictionary : Dictionary> { private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); public V this[ K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9, K10 key10, K11 key11] { get { _lock.EnterReadLock(); try { return ContainsKey(key1) ? this[key1][key2, key3, key4, key5, key6, key7, key8, key9, key10, key11] : default(V); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } set { _lock.EnterWriteLock(); try { if (!ContainsKey(key1)) this[key1] = new MultiKeyDictionary(); this[key1][key2, key3, key4, key5, key6, key7, key8, key9, key10, key11] = value; } finally { if (_lock.IsWriteLockHeld) _lock.ExitWriteLock(); } } } public bool ContainsKey(K1 key1, K2 key2, K3 key3, K4 key4, K5 key5, K6 key6, K7 key7, K8 key8, K9 key9, K10 key10, K11 key11) { _lock.EnterReadLock(); try { return ContainsKey(key1) && this[key1].ContainsKey(key2, key3, key4, key5, key6, key7, key8, key9, key10, key11); } finally { if (_lock.IsReadLockHeld) _lock.ExitReadLock(); } } } }