protected override void Resize()
        {
            int oldCapacity = _table.Length;
            int newCapacity = 2 * oldCapacity;

            bool   mark = false;
            Thread me   = Thread.CurrentThread;

            if (_owner.CompareAndSet(null, me, false, true))
            {
                try
                {
                    if (_table.Length != oldCapacity)
                    { // someone else resized first
                        return;
                    }

                    foreach (Mutex m in _locks)
                    {
                        m.WaitOne();
                        m.ReleaseMutex();
                    }

                    List <T>[] oldTable = _table;
                    _table = new List <T> [newCapacity];
                    for (int i = 0; i < newCapacity; i++)
                    {
                        _table[i] = new List <T>();
                    }

                    _locks = new Mutex[newCapacity];
                    for (int i = 0; i < newCapacity; i++)
                    {
                        _locks[i] = new Mutex();
                    }

                    foreach (List <T> bucket in oldTable)
                    {
                        foreach (T x in bucket)
                        {
                            _table[x.GetHashCode() % _table.Length].Add(x);
                        }
                    }
                }
                finally
                {
                    _owner.Set(null, false);
                }
            }
        }
Ejemplo n.º 2
0
        protected override void Resize()
        {
            int oldCapacity = _table.Length;                 //запоминаем старый размер
            int newCapacity = 2 * oldCapacity;               //вычисляем новый размер

            bool   mark = false;                             //метка изменения размера
            Thread me   = Thread.CurrentThread;              //определяем текущий поток

            if (_owner.CompareAndSet(null, me, false, true)) //если получилось установить себя владельцем изменения
            {
                try
                {
                    if (_table.Length != oldCapacity) //если текущий размер таблицы не совпадает со старым
                    {
                        return;                       //кто=то нас опередил
                    }

                    foreach (Mutex m in _locks) //дожидаемся пока другие отдадут блокировки, потому что менять будем
                    {
                        m.WaitOne();            //по очереди берем все мьютексы
                        m.ReleaseMutex();       //отпускаем все мьютексы
                    }

                    List <T>[] oldTable = _table;        //запоминаем старую таблицу
                    _table = new List <T> [newCapacity]; //инициализирует таблицу новым списком бакетов с новым размером
                    for (int i = 0; i < newCapacity; i++)
                    {
                        _table[i] = new List <T>();  //инициализирует список в каждом бакете
                    }
                    _locks = new Mutex[newCapacity]; //инициализирует таблицу новым списком блокировок с новым размером
                    for (int i = 0; i < newCapacity; i++)
                    {
                        _locks[i] = new Mutex(); //для каждого бакета инициализируем свой мьютекс
                    }

                    foreach (List <T> bucket in oldTable)
                    {
                        foreach (T x in bucket)
                        {
                            _table[x.GetHashCode() % _table.Length].Add(x); //переносит каждый элемент старой таблицы в новую, с учтом нового размера
                        }
                    }
                }
                finally
                {
                    _owner.Set(null, false); //снимает с себя владение измененим размера
                }
            }
        }