wasSharp – Rev 44

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//  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 MultiKeyDictionary<K1, K2, V> : Dictionary<K1, Dictionary<K2, V>>
    {
        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<K2, V>();

                    this[key1][key2] = value;
                }
                finally
                {
                    if (_lock.IsWriteLockHeld) _lock.ExitWriteLock();
                }
            }
        }

        public new IEnumerable<V> 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<K2, V>();

                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<K1, K2, K3, V> : Dictionary<K1, MultiKeyDictionary<K2, K3, V>>
    {
        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 MultiKeyDictionary<K2, K3, V>();

                    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 MultiKeyDictionary<K2, K3, V>();
                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<K1, K2, K3, K4, V> : Dictionary<K1, MultiKeyDictionary<K2, K3, K4, V>>
    {
        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<K2, K3, K4, V>();
                    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<K1, K2, K3, K4, K5, V> : Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, V>>
    {
        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<K2, K3, K4, K5, V>();
                    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<K1, K2, K3, K4, K5, K6, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, V>>
    {
        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<K2, K3, K4, K5, K6, V>();
                    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<K1, K2, K3, K4, K5, K6, K7, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, K7, V>>
    {
        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<K2, K3, K4, K5, K6, K7, V>();
                    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<K1, K2, K3, K4, K5, K6, K7, K8, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, K7, K8, V>>
    {
        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<K2, K3, K4, K5, K6, K7, K8, V>();
                    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<K1, K2, K3, K4, K5, K6, K7, K8, K9, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, K7, K8, K9, V>>
    {
        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<K2, K3, K4, K5, K6, K7, K8, K9, V>();
                    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<K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, K7, K8, K9, K10, V>>
    {
        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<K2, K3, K4, K5, K6, K7, K8, K9, K10, V>();
                    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<K1, K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, V> :
        Dictionary<K1, MultiKeyDictionary<K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, V>>
    {
        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<K2, K3, K4, K5, K6, K7, K8, K9, K10, K11, V>();
                    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();
            }
        }
    }
}