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); } } }
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); //снимает с себя владение измененим размера } } }