You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ni...@apache.org on 2020/02/09 06:15:55 UTC

[lucenenet] 03/35: Lucene.Net.Facet, Lucene.Net.QueryParser: Factored out LurchTable in favor of J2N's implementation

This is an automated email from the ASF dual-hosted git repository.

nightowl888 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/lucenenet.git

commit e315e918275dd9760e12e953bc30da8f8c06689b
Author: Shad Storhaug <sh...@shadstorhaug.com>
AuthorDate: Thu Feb 6 20:10:55 2020 +0700

    Lucene.Net.Facet, Lucene.Net.QueryParser: Factored out LurchTable in favor of J2N's implementation
---
 src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs        |   16 +-
 .../Taxonomy/WriterCache/NameIntCacheLRU.cs        |   31 +-
 .../Xml/Builders/CachedFilterBuilder.cs            |    4 +-
 src/Lucene.Net.Tests/Support/TestLurchTable.cs     |  994 ------------
 .../Support/TestLurchTableThreading.cs             |  278 ----
 src/Lucene.Net/Support/LurchTable.cs               | 1697 --------------------
 6 files changed, 16 insertions(+), 3004 deletions(-)

diff --git a/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs b/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
index 3a673be..3db3a5b 100644
--- a/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
+++ b/src/Lucene.Net.Facet/Taxonomy/LRUHashMap.cs
@@ -1,4 +1,4 @@
-using Lucene.Net.Support;
+using J2N.Collections.Concurrent;
 using System;
 using System.Collections;
 using System.Collections.Generic;
@@ -40,7 +40,7 @@ namespace Lucene.Net.Facet.Taxonomy
     /// </summary>
     public class LRUHashMap<TKey, TValue> : IDictionary<TKey, TValue>
     {
-        private LurchTable<TKey, TValue> cache;
+        private readonly LurchTable<TKey, TValue> cache;
 
         /// <summary>
         /// Create a new hash map with a bounded size and with least recently
@@ -117,7 +117,7 @@ namespace Lucene.Net.Facet.Taxonomy
 
         public TValue Put(TKey key, TValue value)
         {
-            TValue oldValue = default(TValue);
+            TValue oldValue = default;
             cache.AddOrUpdate(key, value, (k, v) =>
             {
                 oldValue = cache[key];
@@ -130,7 +130,7 @@ namespace Lucene.Net.Facet.Taxonomy
         {
             if (!cache.TryGetValue(key, out TValue result))
             {
-                return default(TValue);
+                return default;
             }
             return result;
         }
@@ -168,7 +168,7 @@ namespace Lucene.Net.Facet.Taxonomy
 
         public bool Contains(KeyValuePair<TKey, TValue> item)
         {
-            throw new NotSupportedException();
+            return ((ICollection<KeyValuePair<TKey, TValue>>)cache).Contains(item);
         }
 
         public bool ContainsKey(TKey key)
@@ -176,9 +176,9 @@ namespace Lucene.Net.Facet.Taxonomy
             return cache.ContainsKey(key);
         }
 
-        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
+        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index)
         {
-            throw new NotSupportedException();
+            cache.CopyTo(array, index);
         }
 
         public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
@@ -188,7 +188,7 @@ namespace Lucene.Net.Facet.Taxonomy
 
         public bool Remove(KeyValuePair<TKey, TValue> item)
         {
-            throw new NotSupportedException();
+            return cache.TryRemove(item);
         }
 
         public bool Remove(TKey key)
diff --git a/src/Lucene.Net.Facet/Taxonomy/WriterCache/NameIntCacheLRU.cs b/src/Lucene.Net.Facet/Taxonomy/WriterCache/NameIntCacheLRU.cs
index 2eedc5c..c089885 100644
--- a/src/Lucene.Net.Facet/Taxonomy/WriterCache/NameIntCacheLRU.cs
+++ b/src/Lucene.Net.Facet/Taxonomy/WriterCache/NameIntCacheLRU.cs
@@ -1,4 +1,4 @@
-using Lucene.Net.Support;
+using J2N.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Linq;
 
@@ -38,7 +38,7 @@ namespace Lucene.Net.Facet.Taxonomy.WriterCache
         private IDictionary<object, int> cache;
         internal long nMisses = 0; // for debug
         internal long nHits = 0; // for debug
-        private int maxCacheSize;
+        private readonly int maxCacheSize;
 
         internal NameInt32CacheLRU(int limit)
         {
@@ -49,24 +49,12 @@ namespace Lucene.Net.Facet.Taxonomy.WriterCache
         /// <summary>
         /// Maximum number of cache entries before eviction.
         /// </summary>
-        public virtual int Limit
-        {
-            get
-            {
-                return maxCacheSize;
-            }
-        }
+        public virtual int Limit => maxCacheSize;
 
         /// <summary>
         /// Number of entries currently in the cache.
         /// </summary>
-        public virtual int Count
-        {
-            get
-            {
-                return cache.Count;
-            }
-        }
+        public virtual int Count => cache.Count;
 
         private void CreateCache(int maxSize)
         {
@@ -82,8 +70,7 @@ namespace Lucene.Net.Facet.Taxonomy.WriterCache
 
         internal virtual int Get(FacetLabel name)
         {
-            int result;
-            TryGetValue(name, out result);
+            TryGetValue(name, out int result);
             return result;
         }
 
@@ -131,13 +118,7 @@ namespace Lucene.Net.Facet.Taxonomy.WriterCache
             return IsCacheFull;
         }
 
-        private bool IsCacheFull
-        {
-            get
-            {
-                return cache.Count > maxCacheSize;
-            }
-        }
+        private bool IsCacheFull => cache.Count > maxCacheSize;
 
         internal virtual void Clear()
         {
diff --git a/src/Lucene.Net.QueryParser/Xml/Builders/CachedFilterBuilder.cs b/src/Lucene.Net.QueryParser/Xml/Builders/CachedFilterBuilder.cs
index 7f573ea..63281b1 100644
--- a/src/Lucene.Net.QueryParser/Xml/Builders/CachedFilterBuilder.cs
+++ b/src/Lucene.Net.QueryParser/Xml/Builders/CachedFilterBuilder.cs
@@ -1,5 +1,5 @@
-using Lucene.Net.Search;
-using Lucene.Net.Support;
+using J2N.Collections.Concurrent;
+using Lucene.Net.Search;
 using System.Xml;
 
 namespace Lucene.Net.QueryParsers.Xml.Builders
diff --git a/src/Lucene.Net.Tests/Support/TestLurchTable.cs b/src/Lucene.Net.Tests/Support/TestLurchTable.cs
deleted file mode 100644
index c2ba988..0000000
--- a/src/Lucene.Net.Tests/Support/TestLurchTable.cs
+++ /dev/null
@@ -1,994 +0,0 @@
-using Lucene.Net.Attributes;
-using NUnit.Framework;
-using System;
-using System.Collections.Generic;
-
-namespace Lucene.Net.Support
-{
-    #region Copyright 2012-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
-    /* Licensed under the Apache License, Version 2.0 (the "License");
-     * you may not use this file except in compliance with the License.
-     * You may obtain a copy of the License at
-     * 
-     *   http://www.apache.org/licenses/LICENSE-2.0
-     * 
-     * Unless required by applicable law or agreed to in writing, software
-     * distributed under the License is distributed on an "AS IS" BASIS,
-     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     * See the License for the specific language governing permissions and
-     * limitations under the License.
-     */
-    #endregion
-
-    [TestFixture]
-    public class TestLurchTable : TestGenericCollection<TestLurchTable.LurchTableTest<int, string>, KeyValuePair<int, string>>
-    {
-        public class LurchTableTest<TKey, TValue> : LurchTable<TKey, TValue>
-        {
-            public LurchTableTest() : base(1024, LurchTableOrder.Access)
-            { }
-            public LurchTableTest(LurchTableOrder order) : base(1024, order)
-            { }
-            public LurchTableTest(IEqualityComparer<TKey> comparer) : base(1024, LurchTableOrder.Access, comparer)
-            { }
-        }
-
-        protected override KeyValuePair<int, string>[] GetSample()
-        {
-            var results = new List<KeyValuePair<int, string>>();
-            Random r = new Random();
-            for (int i = 1; i < 100; i += r.Next(1, 3))
-                results.Add(new KeyValuePair<int, string>(i, i.ToString()));
-            return results.ToArray();
-        }
-
-        class IntComparer : IEqualityComparer<int>
-        {
-            bool IEqualityComparer<int>.Equals(int x, int y)
-            {
-                return false;
-            }
-
-            int IEqualityComparer<int>.GetHashCode(int obj)
-            {
-                return 0;
-            }
-        }
-        [Test, LuceneNetSpecific]
-        public void TestCTors()
-        {
-            var cmp = new IntComparer();
-            const int limit = 5;
-
-            Assert.AreEqual(LurchTableOrder.None, new LurchTable<int, int>(1).Ordering);
-            Assert.AreEqual(LurchTableOrder.Insertion, new LurchTable<int, int>(1, LurchTableOrder.Insertion).Ordering);
-            Assert.IsTrue(ReferenceEquals(cmp, new LurchTable<int, int>(1, LurchTableOrder.Insertion, cmp).Comparer));
-            Assert.AreEqual(LurchTableOrder.Modified, new LurchTable<int, int>(LurchTableOrder.Modified, limit).Ordering);
-            Assert.AreEqual(limit, new LurchTable<int, int>(LurchTableOrder.Modified, limit).Limit);
-            Assert.AreEqual(LurchTableOrder.Access, new LurchTable<int, int>(LurchTableOrder.Access, limit, cmp).Ordering);
-            Assert.AreEqual(limit, new LurchTable<int, int>(LurchTableOrder.Access, limit, cmp).Limit);
-            Assert.IsTrue(ReferenceEquals(cmp, new LurchTable<int, int>(LurchTableOrder.Access, limit, cmp).Comparer));
-            Assert.AreEqual(LurchTableOrder.Access, new LurchTable<int, int>(LurchTableOrder.Access, limit, 1, 1, 1, cmp).Ordering);
-            Assert.AreEqual(limit, new LurchTable<int, int>(LurchTableOrder.Access, limit, 1, 1, 1, cmp).Limit);
-            Assert.IsTrue(ReferenceEquals(cmp, new LurchTable<int, int>(LurchTableOrder.Access, limit, 1, 1, 1, cmp).Comparer));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDequeueByInsertion()
-        {
-            var test = new LurchTableTest<int, string>(LurchTableOrder.Insertion);
-            Assert.AreEqual(LurchTableOrder.Insertion, test.Ordering);
-            var sample = GetSample();
-            Array.Reverse(sample);
-            foreach (var item in sample)
-                test.Add(item.Key, item.Value);
-
-            KeyValuePair<int, string> value;
-            foreach (var item in sample)
-            {
-                Assert.IsTrue(test.Peek(out value));
-                Assert.AreEqual(item.Key, value.Key);
-                Assert.AreEqual(item.Value, value.Value);
-                value = test.Dequeue();
-                Assert.AreEqual(item.Key, value.Key);
-                Assert.AreEqual(item.Value, value.Value);
-            }
-
-            Assert.IsFalse(test.Peek(out value));
-            Assert.IsFalse(test.TryDequeue(out value));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDequeueByModified()
-        {
-            var test = new LurchTableTest<int, string>(LurchTableOrder.Modified);
-            Assert.AreEqual(LurchTableOrder.Modified, test.Ordering);
-            var sample = GetSample();
-            foreach (var item in sample)
-                test.Add(item.Key, item.Value);
-
-            Array.Reverse(sample);
-            for (int i = 0; i < sample.Length; i++)
-            {
-                var item = new KeyValuePair<int, string>(sample[i].Key, sample[i].Value + "-2");
-                test[item.Key] = item.Value;
-                sample[i] = item;
-            }
-
-            KeyValuePair<int, string> value;
-            foreach (var item in sample)
-            {
-                Assert.IsTrue(test.Peek(out value));
-                Assert.AreEqual(item.Key, value.Key);
-                Assert.AreEqual(item.Value, value.Value);
-                value = test.Dequeue();
-                Assert.AreEqual(item.Key, value.Key);
-                Assert.AreEqual(item.Value, value.Value);
-            }
-
-            Assert.IsFalse(test.Peek(out value));
-            Assert.IsFalse(test.TryDequeue(out value));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDequeueByAccess()
-        {
-            var test = new LurchTableTest<int, string>(LurchTableOrder.Access);
-            Assert.AreEqual(LurchTableOrder.Access, test.Ordering);
-            var sample = GetSample();
-            foreach (var item in sample)
-                test.Add(item.Key, item.Value);
-
-            Array.Reverse(sample);
-            foreach (var item in sample)
-                Assert.AreEqual(item.Value, test[item.Key]);
-
-            KeyValuePair<int, string> value;
-            foreach (var item in sample)
-            {
-                Assert.IsTrue(test.TryDequeue(out value));
-                Assert.AreEqual(item.Key, value.Key);
-                Assert.AreEqual(item.Value, value.Value);
-            }
-
-            Assert.IsFalse(test.Peek(out value));
-            Assert.IsFalse(test.TryDequeue(out value));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestKeysEnumerator()
-        {
-            var sample = GetSample();
-            var test = CreateSample(sample);
-            int ix = 0;
-            foreach (var key in test.Keys)
-                Assert.AreEqual(sample[ix++].Value, test[key]);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestValuesEnumerator()
-        {
-            var sample = GetSample();
-            var test = CreateSample(sample);
-            int ix = 0;
-            foreach (var value in test.Values)
-                Assert.AreEqual(sample[ix++].Value, value);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestLimitorByAccess()
-        {
-            //multiple of prime will produce hash collision, thus testing removal of non-first elements
-            const int prime = 1103;
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, prime, 10, 10, EqualityComparer<int>.Default);
-            test[1 * prime] = "a";
-            test[2 * prime] = "b";
-            test[3 * prime] = "c";
-            Assert.AreEqual(3, test.Count);
-            Assert.AreEqual("b", test[2 * prime]); //access moves to front..
-            test[4] = "d";
-            test[5] = "e";
-            Assert.AreEqual(3, test.Count); // still 3 items
-            Assert.IsFalse(test.ContainsKey(1 * prime));
-            Assert.IsTrue(test.ContainsKey(2 * prime)); //recently access is still there
-            Assert.IsFalse(test.ContainsKey(3 * prime));
-        }
-
-        class RecordEvents<TKey, TValue>
-        {
-            public KeyValuePair<TKey, TValue> LastAdded, LastUpdate, LastRemove;
-
-            public void ItemAdded(KeyValuePair<TKey, TValue> obj) { LastAdded = obj; }
-            public void ItemUpdated(KeyValuePair<TKey, TValue> original, KeyValuePair<TKey, TValue> obj) { LastUpdate = obj; }
-            public void ItemRemoved(KeyValuePair<TKey, TValue> obj) { LastRemove = obj; }
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCrudEvents()
-        {
-            var recorder = new RecordEvents<int, string>();
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 3, 1103, 10, 10, EqualityComparer<int>.Default);
-            test.ItemAdded += recorder.ItemAdded;
-            test.ItemUpdated += recorder.ItemUpdated;
-            test.ItemRemoved += recorder.ItemRemoved;
-            test[1] = "a";
-            Assert.AreEqual("a", recorder.LastAdded.Value);
-            test[2] = "b";
-            Assert.AreEqual("b", recorder.LastAdded.Value);
-            test[3] = "c";
-            Assert.AreEqual("c", recorder.LastAdded.Value);
-            Assert.AreEqual(3, test.Count);
-            Assert.AreEqual("b", test[2]); //access moves to front..
-            test[4] = "d";
-            Assert.AreEqual("d", recorder.LastAdded.Value);
-            Assert.AreEqual("a", recorder.LastRemove.Value);
-            test[5] = "e";
-            Assert.AreEqual("e", recorder.LastAdded.Value);
-            Assert.AreEqual("c", recorder.LastRemove.Value);
-            test[2] = "B";
-            Assert.AreEqual("B", recorder.LastUpdate.Value);
-            test[6] = "f";
-            Assert.AreEqual("f", recorder.LastAdded.Value);
-            Assert.AreEqual("d", recorder.LastRemove.Value);
-
-            Assert.AreEqual(3, test.Count); // still 3 items
-            string value;
-            Assert.IsTrue(test.TryRemove(5, out value));
-            Assert.AreEqual("e", value);
-            Assert.AreEqual("e", recorder.LastRemove.Value);
-
-            Assert.AreEqual("B", test.Dequeue().Value);
-            Assert.AreEqual("f", test.Dequeue().Value);
-            Assert.AreEqual(0, test.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestCollisionRemoval()
-        {
-            //multiple of prime will produce hash collision, thus testing removal of non-first elements
-            const int prime = 1103;
-            var test = new LurchTable<int, string>(LurchTableOrder.Access, 10, prime, 10, 10, EqualityComparer<int>.Default);
-            test[1 * prime] = "a";
-            test[2 * prime] = "b";
-            test[3 * prime] = "c";
-            test[4 * prime] = "d";
-            test[5 * prime] = "e";
-            Assert.IsTrue(test.Remove(4 * prime));
-            Assert.IsTrue(test.Remove(2 * prime));
-            Assert.IsTrue(test.Remove(5 * prime));
-            Assert.IsTrue(test.Remove(1 * prime));
-            Assert.IsTrue(test.Remove(3 * prime));
-            Assert.AreEqual(0, test.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestAddRemoveByKey()
-        {
-            LurchTableTest<int, string> test = new LurchTableTest<int, string>();
-            for (int i = 0; i < 10; i++)
-                test.Add(i, i.ToString());
-
-            for (int i = 0; i < 10; i++)
-                Assert.IsTrue(test.ContainsKey(i));
-
-            string cmp;
-            for (int i = 0; i < 10; i++)
-                Assert.IsTrue(test.TryGetValue(i, out cmp) && cmp == i.ToString());
-
-            for (int i = 0; i < 10; i++)
-                Assert.IsTrue(test.Remove(i));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestComparer()
-        {
-            var test = new LurchTableTest<string, string>(StringComparer.OrdinalIgnoreCase);
-            test["a"] = "b";
-            Assert.IsTrue(test.ContainsKey("A"));
-
-            test = new LurchTableTest<string, string>(StringComparer.OrdinalIgnoreCase);
-            test["a"] = "b";
-            Assert.IsTrue(test.ContainsKey("A"));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestKeys()
-        {
-            LurchTableTest<string, string> test = new LurchTableTest<string, string>();
-            test["a"] = "b";
-            string all = String.Join("", new List<string>(test.Keys).ToArray());
-            Assert.AreEqual("a", all);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestValues()
-        {
-            LurchTableTest<string, string> test = new LurchTableTest<string, string>();
-            test["a"] = "b";
-            string all = String.Join("", new List<string>(test.Values).ToArray());
-            Assert.AreEqual("b", all);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestAtomicAdd()
-        {
-            var data = new LurchTableTest<int, string>();
-            int[] counter = new int[] { -1 };
-            for (int i = 0; i < 100; i++)
-                Assert.IsTrue(data.TryAdd(i, (k) => (++counter[0]).ToString()));
-            Assert.AreEqual(100, data.Count);
-            Assert.AreEqual(100, counter[0] + 1);
-
-            //Inserts of existing keys will not call method
-            Assert.IsFalse(data.TryAdd(50, (k) => { throw new InvalidOperationException(); }));
-            Assert.AreEqual(100, data.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestAtomicAddOrUpdate()
-        {
-            var data = new LurchTableTest<int, string>();
-            int[] counter = new int[] { -1 };
-
-            for (int i = 0; i < 100; i++)
-                data.AddOrUpdate(i, (k) => (++counter[0]).ToString(), (k, v) => { throw new InvalidOperationException(); });
-
-            for (int i = 0; i < 100; i++)
-                Assert.AreEqual((i & 1) == 1, data.TryRemove(i, (k, v) => (int.Parse(v) & 1) == 1));
-
-            for (int i = 0; i < 100; i++)
-                data.AddOrUpdate(i, (k) => (++counter[0]).ToString(), (k, v) => (++counter[0]).ToString());
-
-            Assert.AreEqual(100, data.Count);
-            Assert.AreEqual(200, counter[0] + 1);
-
-            for (int i = 0; i < 100; i++)
-                Assert.IsTrue(data.TryRemove(i, (k, v) => int.Parse(v) - 100 == i));
-
-            Assert.AreEqual(0, data.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestNewAddOrUpdate()
-        {
-            var data = new LurchTableTest<int, string>();
-            Assert.AreEqual("a", data.AddOrUpdate(1, "a", (k, v) => k.ToString()));
-            Assert.AreEqual("1", data.AddOrUpdate(1, "a", (k, v) => k.ToString()));
-
-            Assert.AreEqual("b", data.AddOrUpdate(2, k => "b", (k, v) => k.ToString()));
-            Assert.AreEqual("2", data.AddOrUpdate(2, k => "b", (k, v) => k.ToString()));
-        }
-
-        struct AddUpdateValue : ICreateOrUpdateValue<int, string>, IRemoveValue<int, string>
-        {
-            public string OldValue;
-            public string Value;
-            public bool CreateValue(int key, out string value)
-            {
-                OldValue = null;
-                value = Value;
-                return Value != null;
-            }
-            public bool UpdateValue(int key, ref string value)
-            {
-                OldValue = value;
-                value = Value;
-                return Value != null;
-            }
-            public bool RemoveValue(int key, string value)
-            {
-                OldValue = value;
-                return value == Value;
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestAtomicInterfaces()
-        {
-            var data = new LurchTableTest<int, string>();
-
-            data[1] = "a";
-
-            AddUpdateValue update = new AddUpdateValue();
-            Assert.IsFalse(data.AddOrUpdate(1, ref update));
-            Assert.AreEqual("a", update.OldValue);
-            Assert.IsFalse(data.AddOrUpdate(2, ref update));
-            Assert.IsNull(update.OldValue);
-            Assert.IsFalse(data.TryRemove(1, ref update));
-            Assert.AreEqual("a", update.OldValue);
-
-            Assert.AreEqual(1, data.Count);
-            Assert.AreEqual("a", data[1]);
-
-            update.Value = "b";
-            Assert.IsTrue(data.AddOrUpdate(1, ref update));
-            Assert.AreEqual("a", update.OldValue);
-            Assert.IsTrue(data.AddOrUpdate(2, ref update));
-            Assert.IsNull(update.OldValue);
-
-            Assert.AreEqual(2, data.Count);
-            Assert.AreEqual("b", data[1]);
-            Assert.AreEqual("b", data[2]);
-
-            Assert.IsTrue(data.TryRemove(1, ref update));
-            Assert.AreEqual("b", update.OldValue);
-            Assert.IsTrue(data.TryRemove(2, ref update));
-            Assert.AreEqual("b", update.OldValue);
-            Assert.AreEqual(0, data.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestGetOrAdd()
-        {
-            var data = new LurchTableTest<int, string>();
-            Assert.AreEqual("a", data.GetOrAdd(1, "a"));
-            Assert.AreEqual("a", data.GetOrAdd(1, "b"));
-
-            Assert.AreEqual("b", data.GetOrAdd(2, k => "b"));
-            Assert.AreEqual("b", data.GetOrAdd(2, k => "c"));
-        }
-
-
-        [Test, LuceneNetSpecific]
-        public void TestTryRoutines()
-        {
-            var data = new LurchTableTest<int, string>();
-
-            Assert.IsTrue(data.TryAdd(1, "a"));
-            Assert.IsFalse(data.TryAdd(1, "a"));
-
-            Assert.IsTrue(data.TryUpdate(1, "a"));
-            Assert.IsTrue(data.TryUpdate(1, "c"));
-            Assert.IsTrue(data.TryUpdate(1, "d", "c"));
-            Assert.IsFalse(data.TryUpdate(1, "f", "c"));
-            Assert.AreEqual("d", data[1]);
-            Assert.IsTrue(data.TryUpdate(1, "a", data[1]));
-            Assert.AreEqual("a", data[1]);
-            Assert.IsFalse(data.TryUpdate(2, "b"));
-
-            string val;
-            Assert.IsTrue(data.TryRemove(1, out val) && val == "a");
-            Assert.IsFalse(data.TryRemove(2, out val));
-            Assert.AreNotEqual(val, "a");
-
-            Assert.IsFalse(data.TryUpdate(1, (k, x) => x.ToUpper()));
-            data[1] = "a";
-            data[1] = "b";
-            Assert.IsTrue(data.TryUpdate(1, (k, x) => x.ToUpper()));
-            Assert.AreEqual("B", data[1]);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestInitialize()
-        {
-            LurchTableTest<string, string> test = new LurchTableTest<string, string>(StringComparer.Ordinal);
-            test["a"] = "b";
-            Assert.AreEqual(1, test.Count);
-            test.Initialize();
-            Assert.AreEqual(0, test.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestSampleCollection()
-        {
-            var sample = GetSample();
-            var items = CreateSample(sample);
-            IDictionary<int, string> dict = items;
-            VerifyCollection(new KeyValueEquality<int, string>(), new List<KeyValuePair<int, string>>(sample), items);
-            VerifyCollection(new KeyValueEquality<int, string>(), new List<KeyValuePair<int, string>>(sample), dict);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestSampleKeyCollection()
-        {
-            var sample = GetSample();
-            var items = CreateSample(sample);
-            IDictionary<int, string> dict = items;
-            var keys = new List<int>();
-            foreach (var kv in sample)
-                keys.Add(kv.Key);
-            VerifyCollection(EqualityComparer<int>.Default, keys.AsReadOnly(), items.Keys);
-            VerifyCollection(EqualityComparer<int>.Default, keys.AsReadOnly(), dict.Keys);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestSampleValueCollection()
-        {
-            var sample = GetSample();
-            var items = CreateSample(sample);
-            IDictionary<int, string> dict = items;
-            var values = new List<string>();
-            foreach (var kv in sample)
-                values.Add(kv.Value);
-            VerifyCollection(EqualityComparer<string>.Default, values.AsReadOnly(), items.Values);
-            VerifyCollection(EqualityComparer<string>.Default, values.AsReadOnly(), dict.Values);
-        }
-
-        [Test]
-        public void TestDisposed()
-        {
-            IDictionary<int, string> test = new LurchTableTest<int, string>();
-            var disposable = test as IDisposable;
-            if (disposable != null)
-            {
-                disposable.Dispose();
-            }
-            Assert.Throws<ObjectDisposedException>(() => { test.Add(1, ""); });
-        }
-
-        class KeyValueEquality<TKey, TValue> : IEqualityComparer<KeyValuePair<TKey, TValue>>
-        {
-            IEqualityComparer<TKey> KeyComparer = EqualityComparer<TKey>.Default;
-            IEqualityComparer<TValue> ValueComparer = EqualityComparer<TValue>.Default;
-            public bool Equals(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
-            {
-                return KeyComparer.Equals(x.Key, y.Key) && ValueComparer.Equals(x.Value, y.Value);
-            }
-            public int GetHashCode(KeyValuePair<TKey, TValue> obj)
-            {
-                return KeyComparer.GetHashCode(obj.Key) ^ ValueComparer.GetHashCode(obj.Value);
-            }
-        }
-    }
-
-    [TestFixture]
-    public class TestLurchTableDictionary : TestDictionary<LurchTable<Guid, String>, TestLurchTableDictionary.Factory, Guid, String>
-    {
-        private const int SAMPLE_SIZE = 1000;
-        public new class Factory : IFactory<LurchTable<Guid, String>>
-        {
-            public LurchTable<Guid, string> Create()
-            {
-                return new LurchTable<Guid, string>(SAMPLE_SIZE, LurchTableOrder.Access);
-            }
-        }
-
-        protected override KeyValuePair<Guid, string>[] GetSample()
-        {
-            var results = new List<KeyValuePair<Guid, string>>();
-            for (int i = 0; i < SAMPLE_SIZE; i++)
-            {
-                Guid id = Guid.NewGuid();
-                results.Add(new KeyValuePair<Guid, string>(id, id.ToString()));
-            }
-            return results.ToArray();
-        }
-    }
-
-
-    #region Support
-
-    #region Abstract classes
-    public abstract class TestGenericCollection<TList, TItem>
-        where TList : ICollection<TItem>, new()
-    {
-        protected abstract TItem[] GetSample();
-
-        protected TList CreateSample(TItem[] items)
-        {
-            TList list = new TList();
-
-            int count = 0;
-            Assert.AreEqual(count, list.Count);
-
-            foreach (TItem item in items)
-            {
-                list.Add(item);
-                Assert.AreEqual(++count, list.Count);
-            }
-            return list;
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestAddRemove()
-        {
-            TList list = new TList();
-            TItem[] items = GetSample();
-
-            int count = 0;
-            Assert.AreEqual(count, list.Count);
-
-            foreach (TItem item in items)
-            {
-                list.Add(item);
-                Assert.AreEqual(++count, list.Count);
-            }
-            foreach (TItem item in items)
-            {
-                Assert.IsTrue(list.Remove(item));
-                Assert.AreEqual(--count, list.Count);
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestAddReverseRemove()
-        {
-            TList list = new TList();
-            TItem[] items = GetSample();
-
-            int count = 0;
-            Assert.AreEqual(count, list.Count);
-
-            foreach (TItem item in items)
-            {
-                list.Add(item);
-                Assert.AreEqual(++count, list.Count);
-            }
-            for (int ix = items.Length - 1; ix >= 0; ix--)
-            {
-                Assert.IsTrue(list.Remove(items[ix]));
-                Assert.AreEqual(--count, list.Count);
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestClear()
-        {
-            TList list = new TList();
-            TItem[] items = GetSample();
-
-            foreach (TItem item in items)
-                list.Add(item);
-            Assert.AreEqual(items.Length, list.Count);
-
-            Assert.AreNotEqual(0, list.Count);
-            list.Clear();
-            Assert.AreEqual(0, list.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestContains()
-        {
-            TList list = new TList();
-            TItem[] items = GetSample();
-
-            foreach (TItem item in items)
-                list.Add(item);
-            Assert.AreEqual(items.Length, list.Count);
-
-            foreach (TItem item in items)
-                Assert.IsTrue(list.Contains(item));
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestCopyTo()
-        {
-            TList list = new TList();
-            List<TItem> items = new List<TItem>(GetSample());
-
-            foreach (TItem item in items)
-                list.Add(item);
-            Assert.AreEqual(items.Count, list.Count);
-
-            TItem[] copy = new TItem[items.Count + 1];
-            list.CopyTo(copy, 1);
-            Assert.AreEqual(default(TItem), copy[0]);
-
-            for (int i = 1; i < copy.Length; i++)
-                Assert.IsTrue(items.Remove(copy[i]));
-
-            Assert.AreEqual(0, items.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestIsReadOnly()
-        {
-            Assert.IsFalse(new TList().IsReadOnly);
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestGetEnumerator()
-        {
-            TList list = new TList();
-            List<TItem> items = new List<TItem>(GetSample());
-
-            foreach (TItem item in items)
-                list.Add(item);
-            Assert.AreEqual(items.Count, list.Count);
-
-            foreach (TItem item in list)
-                Assert.IsTrue(items.Remove(item));
-
-            Assert.AreEqual(0, items.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestGetEnumerator2()
-        {
-            TList list = new TList();
-            List<TItem> items = new List<TItem>(GetSample());
-
-            foreach (TItem item in items)
-                list.Add(item);
-            Assert.AreEqual(items.Count, list.Count);
-
-            foreach (TItem item in ((System.Collections.IEnumerable)list))
-                Assert.IsTrue(items.Remove(item));
-
-            Assert.AreEqual(0, items.Count);
-        }
-
-        public static void VerifyCollection<T, TC>(IEqualityComparer<T> comparer, ICollection<T> expected, TC collection) where TC : ICollection<T>
-        {
-            Assert.AreEqual(expected.IsReadOnly, collection.IsReadOnly);
-            Assert.AreEqual(expected.Count, collection.Count);
-            CompareEnumerations(comparer, expected, collection);
-            using (var a = expected.GetEnumerator())
-            using (var b = collection.GetEnumerator())
-            {
-                bool result;
-                Assert.IsTrue(b.MoveNext());
-                b.Reset();
-                Assert.AreEqual(result = a.MoveNext(), b.MoveNext());
-                while (result)
-                {
-                    Assert.IsTrue(comparer.Equals(a.Current, b.Current));
-                    Assert.IsTrue(comparer.Equals(a.Current, (T)((System.Collections.IEnumerator)b).Current));
-                    Assert.AreEqual(result = a.MoveNext(), b.MoveNext());
-                }
-            }
-
-            T[] items = new T[10 + collection.Count];
-            collection.CopyTo(items, 5);
-            Array.Copy(items, 5, items, 0, collection.Count);
-            Array.Resize(ref items, collection.Count);
-            CompareEnumerations(comparer, expected, collection);
-
-            for (int i = 0; i < 5; i++)
-                Assert.IsTrue(collection.Contains(items[i]));
-        }
-
-        public static void CompareEnumerations<T>(IEqualityComparer<T> comparer, IEnumerable<T> expected, IEnumerable<T> collection)
-        {
-            using (var a = expected.GetEnumerator())
-            using (var b = collection.GetEnumerator())
-            {
-                bool result;
-                Assert.AreEqual(result = a.MoveNext(), b.MoveNext());
-                while (result)
-                {
-                    Assert.IsTrue(comparer.Equals(a.Current, b.Current));
-                    Assert.AreEqual(result = a.MoveNext(), b.MoveNext());
-                }
-            }
-        }
-    }
-
-    public abstract class TestDictionary<TDictionary, TFactory, TKey, TValue> : TestCollection<TDictionary, TFactory, KeyValuePair<TKey, TValue>>
-        where TDictionary : IDictionary<TKey, TValue>, IDisposable
-        where TFactory : IFactory<TDictionary>, new()
-    {
-        [Test, LuceneNetSpecific]
-        public virtual void TestAddRemoveByKey()
-        {
-            KeyValuePair<TKey, TValue>[] sample = GetSample();
-
-            using (TDictionary test = Factory.Create())
-            {
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                    test.Add(kv.Key, kv.Value);
-
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                    Assert.IsTrue(test.ContainsKey(kv.Key));
-
-                TValue cmp;
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                    Assert.IsTrue(test.TryGetValue(kv.Key, out cmp) && kv.Value.Equals(cmp));
-
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                    Assert.IsTrue(test.Remove(kv.Key));
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestKeys()
-        {
-            KeyValuePair<TKey, TValue>[] sample = GetSample();
-
-            using (TDictionary test = Factory.Create())
-            {
-                List<TKey> keys = new List<TKey>();
-
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                {
-                    test[kv.Key] = kv.Value;
-                    keys.Add(kv.Key);
-                }
-
-                List<TKey> cmp = new List<TKey>(test.Keys);
-
-                Assert.AreEqual(keys.Count, cmp.Count);
-                for (int i = 0; i < keys.Count; i++)
-                    Assert.IsTrue(test.ContainsKey(keys[i]));
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestValues()
-        {
-            KeyValuePair<TKey, TValue>[] sample = GetSample();
-
-            using (TDictionary test = Factory.Create())
-            {
-                List<TValue> values = new List<TValue>();
-
-                foreach (KeyValuePair<TKey, TValue> kv in sample)
-                {
-                    test[kv.Key] = kv.Value;
-                    values.Add(kv.Value);
-                }
-
-                List<TValue> cmp = new List<TValue>(test.Values);
-                Assert.AreEqual(values.Count, cmp.Count);
-            }
-        }
-    }
-
-    public abstract class TestCollection<TList, TFactory, TItem>
-        where TList : ICollection<TItem>, IDisposable
-        where TFactory : IFactory<TList>, new()
-    {
-        protected abstract TItem[] GetSample();
-
-        protected readonly TFactory Factory = new TFactory();
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestAddRemove()
-        {
-            using (TList list = Factory.Create())
-            {
-                TItem[] items = GetSample();
-
-                int count = 0;
-                Assert.AreEqual(count, list.Count);
-
-                foreach (TItem item in items)
-                {
-                    list.Add(item);
-                    Assert.AreEqual(++count, list.Count);
-                }
-                foreach (TItem item in items)
-                {
-                    Assert.IsTrue(list.Remove(item));
-                    Assert.AreEqual(--count, list.Count);
-                }
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestAddReverseRemove()
-        {
-            using (TList list = Factory.Create())
-            {
-                TItem[] items = GetSample();
-
-                int count = 0;
-                Assert.AreEqual(count, list.Count);
-
-                foreach (TItem item in items)
-                {
-                    list.Add(item);
-                    Assert.AreEqual(++count, list.Count);
-                }
-                for (int ix = items.Length - 1; ix >= 0; ix--)
-                {
-                    Assert.IsTrue(list.Remove(items[ix]));
-                    Assert.AreEqual(--count, list.Count);
-                }
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestClear()
-        {
-            using (TList list = Factory.Create())
-            {
-                TItem[] items = GetSample();
-
-                foreach (TItem item in items)
-                    list.Add(item);
-                Assert.AreEqual(items.Length, list.Count);
-
-                Assert.AreNotEqual(0, list.Count);
-                list.Clear();
-                Assert.AreEqual(0, list.Count);
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestContains()
-        {
-            using (TList list = Factory.Create())
-            {
-                TItem[] items = GetSample();
-
-                foreach (TItem item in items)
-                    list.Add(item);
-                Assert.AreEqual(items.Length, list.Count);
-
-                foreach (TItem item in items)
-                    Assert.IsTrue(list.Contains(item));
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestCopyTo()
-        {
-            using (TList list = Factory.Create())
-            {
-                List<TItem> items = new List<TItem>(GetSample());
-
-                foreach (TItem item in items)
-                    list.Add(item);
-                Assert.AreEqual(items.Count, list.Count);
-
-                TItem[] copy = new TItem[items.Count + 1];
-                list.CopyTo(copy, 1);
-                Assert.AreEqual(default(TItem), copy[0]);
-
-                for (int i = 1; i < copy.Length; i++)
-                    Assert.IsTrue(items.Remove(copy[i]));
-
-                Assert.AreEqual(0, items.Count);
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestIsReadOnly()
-        {
-            using (TList list = Factory.Create())
-                Assert.IsFalse(list.IsReadOnly);
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestGetEnumerator()
-        {
-            using (TList list = Factory.Create())
-            {
-                List<TItem> items = new List<TItem>(GetSample());
-
-                foreach (TItem item in items)
-                    list.Add(item);
-                Assert.AreEqual(items.Count, list.Count);
-
-                foreach (TItem item in list)
-                    Assert.IsTrue(items.Remove(item));
-
-                Assert.AreEqual(0, items.Count);
-            }
-        }
-
-        [Test, LuceneNetSpecific]
-        public virtual void TestGetEnumerator2()
-        {
-            using (TList list = Factory.Create())
-            {
-                List<TItem> items = new List<TItem>(GetSample());
-
-                foreach (TItem item in items)
-                    list.Add(item);
-                Assert.AreEqual(items.Count, list.Count);
-
-                foreach (TItem item in ((System.Collections.IEnumerable)list))
-                    Assert.IsTrue(items.Remove(item));
-
-                Assert.AreEqual(0, items.Count);
-            }
-        }
-    }
-
-    #endregion
-
-    #region Interfaces
-
-    /// <summary> Generic factory for instances of type T </summary>
-    public interface IFactory<T>
-    {
-        /// <summary> Creates an instance of an object assignable to type T </summary>
-        T Create();
-    }
-
-    #endregion
-
-    #endregion
-}
diff --git a/src/Lucene.Net.Tests/Support/TestLurchTableThreading.cs b/src/Lucene.Net.Tests/Support/TestLurchTableThreading.cs
deleted file mode 100644
index 0e08523..0000000
--- a/src/Lucene.Net.Tests/Support/TestLurchTableThreading.cs
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-using Lucene.Net.Attributes;
-using NUnit.Framework;
-using System;
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Threading;
-
-namespace Lucene.Net.Support
-{
-    [TestFixture]
-    public class TestLurchTableThreading
-    {
-        private const int MAXTHREADS = 8;
-        private const int COUNT = 1000;
-        static LurchTable<Guid, T> CreateMap<T>()
-        {
-            var ht = new LurchTable<Guid, T>(COUNT, LurchTableOrder.Access);
-            return ht;
-        }
-
-        private static void Parallel<T>(int loopCount, T[] args, Action<T> task)
-        {
-            var timer = Stopwatch.StartNew();
-            int[] ready = new[] { 0 };
-            ManualResetEvent start = new ManualResetEvent(false);
-            int nthreads = Math.Min(MAXTHREADS, args.Length);
-            var threads = new Thread[nthreads];
-            for (int i = 0; i < threads.Length; i++)
-            {
-                threads[i] = new Thread((ithread) =>
-                {
-                    Interlocked.Increment(ref ready[0]);
-                    start.WaitOne();
-                    for (int loop = 0; loop < loopCount; loop++)
-                        for (int ix = (int)ithread; ix < args.Length; ix += nthreads)
-                            task(args[ix]);
-                });
-            }
-
-            int threadIx = 0;
-            foreach (var t in threads)
-                t.Start(threadIx++);
-
-            while (Interlocked.CompareExchange(ref ready[0], 0, 0) < nthreads)
-                Thread.Sleep(0);
-
-            start.Set();
-
-            foreach (var t in threads)
-                t.Join();
-
-            Trace.TraceInformation("Execution time: {0}", timer.Elapsed);
-        }
-
-        // LUCENENET TODO: For some reason, this logic depends on the underlying
-        // implementation of Guid.NewGuid(), which has changed in .NET Core 2.0.
-        // But the functionality of LurchTable seems unaffected by this change.
-#if !NETCOREAPP
-        [Test, LuceneNetSpecific]
-        public void TestGuidHashCollision()
-        {
-            Guid id1 = Guid.NewGuid();
-            Guid id2 = NextHashCollision(id1);
-
-            Assert.AreNotEqual(id1, id2);
-            Assert.AreEqual(id1.GetHashCode(), id2.GetHashCode());
-        }
-#endif
-
-        [Test, LuceneNetSpecific]
-        public void TestLimitedInsert()
-        {
-            var Map = new LurchTable<Guid, bool>(LurchTableOrder.Access, 1000);
-            var ids = CreateSample(Guid.NewGuid(), 1000000, 0);
-
-            Parallel(1, ids,
-                     id =>
-                     {
-                         bool test;
-                         Assert.IsTrue(Map.TryAdd(id, true));
-                         Map.TryGetValue(id, out test);
-                     });
-
-            Assert.AreEqual(1000, Map.Count);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestInsert()
-        {
-            var Map = CreateMap<bool>();
-            var ids = CreateSample(Guid.NewGuid(), COUNT, 4);
-
-            bool test;
-            Parallel(1, ids, id => { Assert.IsTrue(Map.TryAdd(id, true)); });
-
-            Assert.AreEqual(ids.Length, Map.Count);
-            foreach (var id in ids)
-                Assert.IsTrue(Map.TryGetValue(id, out test) && test);
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestDelete()
-        {
-            var Map = CreateMap<bool>();
-            var ids = CreateSample(Guid.NewGuid(), COUNT, 4);
-            foreach (var id in ids)
-                Assert.IsTrue(Map.TryAdd(id, true));
-
-            bool test;
-            Parallel(1, ids, id => { Assert.IsTrue(Map.Remove(id)); });
-
-            Assert.AreEqual(0, Map.Count);
-            foreach (var id in ids)
-                Assert.IsTrue(!Map.TryGetValue(id, out test));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestInsertDelete()
-        {
-            var Map = CreateMap<bool>();
-            var ids = CreateSample(Guid.NewGuid(), COUNT, 4);
-
-            bool test;
-            Parallel(100, ids, id => { Assert.IsTrue(Map.TryAdd(id, true)); Assert.IsTrue(Map.Remove(id)); });
-
-            Assert.AreEqual(0, Map.Count);
-            foreach (var id in ids)
-                Assert.IsTrue(!Map.TryGetValue(id, out test));
-        }
-
-        [Test, LuceneNetSpecific]
-        public void TestInsertUpdateDelete()
-        {
-            var Map = CreateMap<bool>();
-            var ids = CreateSample(Guid.NewGuid(), COUNT, 4);
-
-            bool test;
-            Parallel(100, ids, id => { Assert.IsTrue(Map.TryAdd(id, true)); Assert.IsTrue(Map.TryUpdate(id, false, true)); Assert.IsTrue(Map.Remove(id)); });
-
-            Assert.AreEqual(0, Map.Count);
-            foreach (var id in ids)
-                Assert.IsTrue(!Map.TryGetValue(id, out test));
-        }
-
-        [Test, LongRunningTest, LuceneNetSpecific]
-        public void CompareTest()
-        {
-            const int size = 1000000;
-            int reps = 3;
-            Stopwatch timer;
-
-            IDictionary<Guid, TestValue> dict = new ConcurrentDictionary<Guid, TestValue>(new Dictionary<Guid, TestValue>(size));
-            IDictionary<Guid, TestValue> test = new LurchTable<Guid, TestValue>(size);
-
-            for (int rep = 0; rep < reps; rep++)
-            {
-                var sample = CreateSample(Guid.NewGuid(), size, 1);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => dict.Add(item, new TestValue { Id = item, Count = rep }));
-                Trace.TraceInformation("Dict Add: {0}", timer.Elapsed);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => test.Add(item, new TestValue { Id = item, Count = rep }));
-                Trace.TraceInformation("Test Add: {0}", timer.Elapsed);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => dict[item] = new TestValue { Id = item, Count = rep });
-                Trace.TraceInformation("Dict Update: {0}", timer.Elapsed);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => test[item] = new TestValue { Id = item, Count = rep });
-                Trace.TraceInformation("Test Update: {0}", timer.Elapsed);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => dict.Remove(item));
-                Trace.TraceInformation("Dict Rem: {0}", timer.Elapsed);
-                Assert.AreEqual(0, dict.Count);
-
-                timer = Stopwatch.StartNew();
-                Parallel(1, sample, item => test.Remove(item));
-                Trace.TraceInformation("Test Rem: {0}", timer.Elapsed);
-
-                test.Clear();
-                dict.Clear();
-
-                GC.Collect();
-                GC.WaitForPendingFinalizers();
-            }
-        }
-
-        struct TestValue
-        {
-            public Guid Id;
-            public int Count;
-        };
-
-#region Guid Hash Collision Generator
-
-        private static Random random = new Random();
-        private static int iCounter = 0x01010101;
-
-        public static Guid NextHashCollision(Guid guid)
-        {
-            var bytes = guid.ToByteArray();
-
-            // Modify bytes 8 & 9 with random number
-            Array.Copy(
-                BitConverter.GetBytes((short)random.Next()),
-                0,
-                bytes,
-                8,
-                2
-            );
-
-            // Increment bytes 11, 12, 13, & 14
-            Array.Copy(
-                BitConverter.GetBytes(
-                    BitConverter.ToInt32(bytes, 11) +
-                    Interlocked.Increment(ref iCounter)
-                    ),
-                0,
-                bytes,
-                11,
-                4
-            );
-
-            Guid result = new Guid(bytes);
-#if !NETCOREAPP
-            Assert.AreEqual(guid.GetHashCode(), result.GetHashCode());
-#endif
-            return result;
-        }
-
-        public static Guid[] CreateSample(Guid seed, int size, double collisions)
-        {
-            var sample = new Guid[size];
-            int count = 0, collis = 0, uix = 0;
-            for (int i = 0; i < size; i++)
-            {
-                if (collis >= count * collisions)
-                {
-                    sample[uix = i] = Guid.NewGuid();
-                    count++;
-                }
-                else
-                {
-                    sample[i] = NextHashCollision(sample[uix]);
-                    collis++;
-                }
-            }
-            return sample;
-        }
-#endregion
-    }
-}
diff --git a/src/Lucene.Net/Support/LurchTable.cs b/src/Lucene.Net/Support/LurchTable.cs
deleted file mode 100644
index cb496d4..0000000
--- a/src/Lucene.Net/Support/LurchTable.cs
+++ /dev/null
@@ -1,1697 +0,0 @@
-#region Copyright 2012-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0
-/* Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *   http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
- // 2016-10-03: Modified from the original version by Shad Storhaug to 
- //             allow read-write access to the Limit property
-#endregion
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Threading;
-
-namespace Lucene.Net.Support
-{
-    /// <summary>
-    /// Defines if and how items added to a LurchTable are linked together, this defines
-    /// the value returned from Peek/Dequeue as the oldest entry of the specified operation.
-    /// </summary>
-    public enum LurchTableOrder
-    {
-        /// <summary> No linking </summary>
-        None,
-        /// <summary> Linked in insertion order </summary>
-        Insertion,
-        /// <summary> Linked by most recently inserted or updated </summary>
-        Modified,
-        /// <summary> Linked by most recently inserted, updated, or fetched </summary>
-        Access,
-    }
-
-    /// <summary>
-    /// LurchTable stands for "Least Used Recently Concurrent Hash Table" and has definate
-    /// similarities to both the .NET 4 ConcurrentDictionary as well as Java's LinkedHashMap.
-    /// This gives you a thread-safe dictionary/hashtable that stores element ordering by
-    /// insertion, updates, or access.  In addition it can be configured to use a 'hard-limit'
-    /// count of items that will automatically 'pop' the oldest item in the collection.
-    /// </summary>
-    /// <typeparam name="TKey">The type of keys in the dictionary.</typeparam>
-    /// <typeparam name="TValue">The type of values in the dictionary.</typeparam>
-    public class LurchTable<TKey, TValue> : IDictionary<TKey, TValue>, IDisposable
-    {
-        /// <summary> Method signature for the ItemUpdated event </summary>
-        public delegate void ItemUpdatedMethod(KeyValuePair<TKey, TValue> previous, KeyValuePair<TKey, TValue> next);
-
-        /// <summary> Event raised after an item is removed from the collection </summary>
-        public event Action<KeyValuePair<TKey, TValue>> ItemRemoved;
-        /// <summary> Event raised after an item is updated in the collection </summary>
-        public event ItemUpdatedMethod ItemUpdated;
-        /// <summary> Event raised after an item is added to the collection </summary>
-        public event Action<KeyValuePair<TKey, TValue>> ItemAdded;
-
-        private const int OverAlloc = 128;
-        private const int FreeSlots = 32;
-
-        private readonly IEqualityComparer<TKey> _comparer;
-        private readonly int _hsize, _lsize;
-        private int _limit; // LUCENENET: Changed to read-write
-        private readonly int _allocSize, _shift, _shiftMask;
-        private readonly LurchTableOrder _ordering;
-        private readonly object[] _locks;
-        private readonly int[] _buckets;
-        private readonly FreeList[] _free;
-
-        private Entry[][] _entries;
-        private int _used, _count;
-        private int _allocNext, _freeVersion;
-
-
-
-        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
-        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
-        public LurchTable(int capacity)
-            : this(LurchTableOrder.None, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, null) { }
-
-        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
-        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
-        /// <param name="ordering">The type of linking for the items</param>
-        public LurchTable(int capacity, LurchTableOrder ordering)
-            : this(ordering, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, null) { }
-
-        /// <summary>Creates a LurchTable that can store up to <paramref name="capacity"/> items efficiently.</summary>
-        /// <param name="capacity">The initial allowable number of items before allocation of more memory</param>
-        /// <param name="ordering">The type of linking for the items</param>
-        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="EqualityComparer{TKey}.Default"/></param>
-        public LurchTable(int capacity, LurchTableOrder ordering, IEqualityComparer<TKey> comparer)
-            : this(ordering, int.MaxValue, capacity >> 1, capacity >> 4, capacity >> 8, comparer) { }
-
-        /// <summary>Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.</summary>
-        /// <param name="ordering">The type of linking for the items</param>
-        /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
-        public LurchTable(LurchTableOrder ordering, int limit)
-            : this(ordering, limit, limit >> 1, limit >> 4, limit >> 8, null) { }
-
-        /// <summary>Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.</summary>
-        /// <param name="ordering">The type of linking for the items</param>
-        /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
-        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="EqualityComparer{TKey}.Default"/></param>
-        public LurchTable(LurchTableOrder ordering, int limit, IEqualityComparer<TKey> comparer)
-            : this(ordering, limit, limit >> 1, limit >> 4, limit >> 8, comparer) { }
-
-        /// <summary>
-        /// Creates a LurchTable that orders items by <paramref name="ordering"/> and removes items once the specified <paramref name="limit"/> is reached.
-        /// </summary>
-        /// <param name="ordering">The type of linking for the items</param>
-        /// <param name="limit">The maximum allowable number of items, or int.MaxValue for unlimited</param>
-        /// <param name="hashSize">The number of hash buckets to use for the collection, usually 1/2 estimated capacity</param>
-        /// <param name="allocSize">The number of entries to allocate at a time, usually 1/16 estimated capacity</param>
-        /// <param name="lockSize">The number of concurrency locks to preallocate, usually 1/256 estimated capacity</param>
-        /// <param name="comparer">The element hash generator for keys, or <c>null</c> to use <see cref="EqualityComparer{TKey}.Default"/></param>
-        public LurchTable(LurchTableOrder ordering, int limit, int hashSize, int allocSize, int lockSize, IEqualityComparer<TKey> comparer)
-        {
-            if (limit <= 0)
-                throw new ArgumentOutOfRangeException("limit");
-            if (ordering == LurchTableOrder.None && limit < int.MaxValue)
-                throw new ArgumentOutOfRangeException("ordering");
-
-            _limit = limit <= 0 ? int.MaxValue : limit;
-            _comparer = comparer ?? EqualityComparer<TKey>.Default;
-            _ordering = ordering;
-
-            allocSize = (int)Math.Min((long)allocSize + OverAlloc, 0x3fffffff);
-            //last power of 2 that is less than allocSize
-            for (_shift = 7; _shift < 24 && (1 << (_shift + 1)) < allocSize; _shift++) { }
-            _allocSize = 1 << _shift;
-            _shiftMask = _allocSize - 1;
-
-            _hsize = HashUtilities.SelectPrimeNumber(Math.Max(127, hashSize));
-            _buckets = new int[_hsize];
-
-            _lsize = HashUtilities.SelectPrimeNumber(lockSize);
-            _locks = new object[_lsize];
-            for (int i = 0; i < _lsize; i++)
-                _locks[i] = new object();
-
-            _free = new FreeList[FreeSlots];
-            Initialize();
-        }
-
-        #region IDisposable Members
-
-        /// <summary>
-        /// Clears references to all objects and invalidates the collection
-        /// </summary>
-        public void Dispose()
-        {
-            _entries = null;
-            _used = _count = 0;
-        }
-
-        #endregion
-
-        /// <summary>
-        /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
-        /// </summary>
-        public int Count { get { return _count; } }
-        /// <summary>
-        /// Retrieves the LurchTableOrder Ordering enumeration this instance was created with.
-        /// </summary>
-        public LurchTableOrder Ordering { get { return _ordering; } }
-        /// <summary>
-        /// Retrives the key comparer being used by this instance.
-        /// </summary>
-        public IEqualityComparer<TKey> Comparer { get { return _comparer; } }
-        /// <summary>
-        /// Gets or Sets the record limit allowed in this instance.
-        /// </summary>
-        public int Limit
-        {
-            get { return _limit; }
-            set { _limit = value; }
-        }
-
-        /// <summary>
-        /// WARNING: not thread-safe, reinitializes all internal structures.  Use Clear() for a thread-safe
-        /// delete all.  If you have externally provided exclusive access this method may be used to more
-        /// efficiently clear the collection.
-        /// </summary>
-        public void Initialize()
-        {
-            lock (this)
-            {
-                _freeVersion = _allocNext = 0;
-                _count = 0;
-                _used = 1;
-
-                Array.Clear(_buckets, 0, _hsize);
-                _entries = new[] { new Entry[_allocSize] };
-                for (int slot = 0; slot < FreeSlots; slot++)
-                {
-                    var index = Interlocked.CompareExchange(ref _used, _used + 1, _used);
-                    if (index != slot + 1)
-                        throw new LurchTableCorruptionException();
-
-                    _free[slot].Tail = index;
-                    _free[slot].Head = index;
-                }
-
-                if (_count != 0 || _used != FreeSlots + 1)
-                    throw new LurchTableCorruptionException();
-            }
-        }
-
-        #region IDictionary<TKey,TValue> Members
-
-        /// <summary>
-        /// Removes all items from the <see cref="T:System.Collections.Generic.ICollection`1"/>.
-        /// </summary>
-        public void Clear()
-        {
-            if (_entries == null) throw new ObjectDisposedException(GetType().Name);
-            foreach (var item in this)
-                Remove(item.Key);
-        }
-
-        /// <summary>
-        /// Determines whether the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key.
-        /// </summary>
-        public bool ContainsKey(TKey key)
-        {
-            if (_entries == null) throw new ObjectDisposedException(GetType().Name);
-            TValue value;
-            return TryGetValue(key, out value);
-        }
-
-        /// <summary>
-        /// Gets or sets the element with the specified key.
-        /// </summary>
-        public TValue this[TKey key]
-        {
-            set
-            {
-                var info = new AddInfo<TKey, TValue> { Value = value, CanUpdate = true };
-                Insert(key, ref info);
-            }
-            get
-            {
-                TValue value;
-                if (!TryGetValue(key, out value))
-                    throw new ArgumentOutOfRangeException();
-                return value;
-            }
-        }
-
-        /// <summary>
-        /// Gets the value associated with the specified key.
-        /// </summary>
-        /// <returns>
-        /// true if the object that implements <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key; otherwise, false.
-        /// </returns>
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            int hash = _comparer.GetHashCode(key) & int.MaxValue;
-            return InternalGetValue(hash, key, out value);
-        }
-
-        /// <summary>
-        /// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        public void Add(TKey key, TValue value)
-        {
-            var info = new AddInfo<TKey, TValue> { Value = value };
-            if (InsertResult.Inserted != Insert(key, ref info))
-                throw new ArgumentOutOfRangeException();
-        }
-
-        /// <summary>
-        /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        /// <returns>
-        /// true if the element is successfully removed; otherwise, false.  This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </returns>
-        /// <param name="key">The key of the element to remove.</param>
-        public bool Remove(TKey key)
-        {
-            var del = new DelInfo<TKey, TValue>();
-            return Delete(key, ref del);
-        }
-
-        #endregion
-
-        #region IDictionaryEx<TKey,TValue> Members
-
-        /// <summary>
-        /// Adds a key/value pair to the  <see cref="T:System.Collections.Generic.IDictionary`2"/> if the key does not already exist.
-        /// </summary>
-        /// <param name="key">The key of the element to add.</param>
-        /// <param name="value">The value to be added, if the key does not already exist.</param>
-        public TValue GetOrAdd(TKey key, TValue value)
-        {
-            var info = new AddInfo<TKey, TValue> { Value = value, CanUpdate = false };
-            if (InsertResult.Exists == Insert(key, ref info))
-                return info.Value;
-            return value;
-        }
-
-        /// <summary>
-        /// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        /// <param name="key">The object to use as the key of the element to add.</param>
-        /// <param name="value">The object to use as the value of the element to add.</param>
-        public bool TryAdd(TKey key, TValue value)
-        {
-            var info = new AddInfo<TKey, TValue> { Value = value, CanUpdate = false };
-            return InsertResult.Inserted == Insert(key, ref info);
-        }
-
-        /// <summary>
-        /// Updates an element with the provided key to the value if it exists.
-        /// </summary>
-        /// <returns>Returns true if the key provided was found and updated to the value.</returns>
-        /// <param name="key">The object to use as the key of the element to update.</param>
-        /// <param name="value">The new value for the key if found.</param>
-        public bool TryUpdate(TKey key, TValue value)
-        {
-            var info = new UpdateInfo<TKey, TValue> { Value = value };
-            return InsertResult.Updated == Insert(key, ref info);
-        }
-
-        /// <summary>
-        /// Updates an element with the provided key to the value if it exists.
-        /// </summary>
-        /// <returns>Returns true if the key provided was found and updated to the value.</returns>
-        /// <param name="key">The object to use as the key of the element to update.</param>
-        /// <param name="value">The new value for the key if found.</param>
-        /// <param name="comparisonValue">The value that is compared to the value of the element with key.</param>
-        public bool TryUpdate(TKey key, TValue value, TValue comparisonValue)
-        {
-            var info = new UpdateInfo<TKey, TValue>(comparisonValue) { Value = value };
-            return InsertResult.Updated == Insert(key, ref info);
-        }
-
-        /// <summary>
-        /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        /// <returns>
-        /// true if the element is successfully removed; otherwise, false.  This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </returns>
-        /// <param name="key">The key of the element to remove.</param>
-        /// <param name="value">The value that was removed.</param>
-        public bool TryRemove(TKey key, out TValue value)
-        {
-            var info = new DelInfo<TKey, TValue>();
-            if (Delete(key, ref info))
-            {
-                value = info.Value;
-                return true;
-            }
-            value = default(TValue);
-            return false;
-        }
-
-        #endregion
-
-        #region IConcurrentDictionary<TKey,TValue> Members
-
-        /// <summary>
-        /// Adds a key/value pair to the  <see cref="T:System.Collections.Generic.IDictionary`2"/> if the key does not already exist.
-        /// </summary>
-        /// <param name="key">The key of the element to add.</param>
-        /// <param name="fnCreate">Constructs a new value for the key.</param>
-        public TValue GetOrAdd(TKey key, Func<TKey, TValue> fnCreate)
-        {
-            var info = new Add2Info<TKey, TValue> { Create = fnCreate };
-            Insert(key, ref info);
-            return info.Value;
-        }
-
-        /// <summary>
-        /// Adds a key/value pair to the <see cref="T:System.Collections.Generic.IDictionary`2"/> if the key does not already exist, 
-        /// or updates a key/value pair if the key already exists.
-        /// </summary>
-        public TValue AddOrUpdate(TKey key, TValue addValue, KeyValueUpdate<TKey, TValue> fnUpdate)
-        {
-            var info = new Add2Info<TKey, TValue>(addValue) { Update = fnUpdate };
-            Insert(key, ref info);
-            return info.Value;
-        }
-
-        /// <summary>
-        /// Adds a key/value pair to the <see cref="T:System.Collections.Generic.IDictionary`2"/> if the key does not already exist, 
-        /// or updates a key/value pair if the key already exists.
-        /// </summary>
-        /// <remarks>
-        /// Adds or modifies an element with the provided key and value.  If the key does not exist in the collection,
-        /// the factory method fnCreate will be called to produce the new value, if the key exists, the converter method
-        /// fnUpdate will be called to create an updated value.
-        /// </remarks>
-        public TValue AddOrUpdate(TKey key, Func<TKey, TValue> fnCreate, KeyValueUpdate<TKey, TValue> fnUpdate)
-        {
-            var info = new Add2Info<TKey, TValue> { Create = fnCreate, Update = fnUpdate };
-            Insert(key, ref info);
-            return info.Value;
-        }
-
-        /// <summary>
-        /// Add, update, or fetche a key/value pair from the dictionary via an implementation of the
-        /// <see cref="T:CSharpTest.Net.Collections.ICreateOrUpdateValue`2"/> interface.
-        /// </summary>
-        public bool AddOrUpdate<T>(TKey key, ref T createOrUpdateValue) where T : ICreateOrUpdateValue<TKey, TValue>
-        {
-            var result = Insert(key, ref createOrUpdateValue);
-            return result == InsertResult.Inserted || result == InsertResult.Updated;
-        }
-
-        /// <summary>
-        /// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2"/>
-        /// by calling the provided factory method to construct the value if the key is not already present in the collection.
-        /// </summary>
-        public bool TryAdd(TKey key, Func<TKey, TValue> fnCreate)
-        {
-            var info = new Add2Info<TKey, TValue> { Create = fnCreate };
-            return InsertResult.Inserted == Insert(key, ref info);
-        }
-
-        /// <summary>
-        /// Modify the value associated with the result of the provided update method
-        /// as an atomic operation, Allows for reading/writing a single record within
-        /// the syncronization lock.
-        /// </summary>
-        public bool TryUpdate(TKey key, KeyValueUpdate<TKey, TValue> fnUpdate)
-        {
-            var info = new Add2Info<TKey, TValue> { Update = fnUpdate };
-            return InsertResult.Updated == Insert(key, ref info);
-        }
-
-        /// <summary>
-        /// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>
-        /// if the fnCondition predicate is null or returns true.
-        /// </summary>
-        public bool TryRemove(TKey key, KeyValuePredicate<TKey, TValue> fnCondition)
-        {
-            var info = new DelInfo<TKey, TValue> { Condition = fnCondition };
-            return Delete(key, ref info);
-        }
-
-        /// <summary>
-        /// Conditionally removes a key/value pair from the dictionary via an implementation of the
-        /// <see cref="T:CSharpTest.Net.Collections.IRemoveValue`2"/> interface.
-        /// </summary>
-        public bool TryRemove<T>(TKey key, ref T removeValue) where T : IRemoveValue<TKey, TValue>
-        {
-            return Delete(key, ref removeValue);
-        }
-
-        #endregion
-
-        #region ICollection<KeyValuePair<TKey,TValue>> Members
-
-        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
-        {
-            get { return false; }
-        }
-
-        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
-        {
-            Add(item.Key, item.Value);
-        }
-
-        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
-        {
-            TValue test;
-            if (TryGetValue(item.Key, out test))
-                return EqualityComparer<TValue>.Default.Equals(item.Value, test);
-            return false;
-        }
-
-        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
-        {
-            foreach (var item in this)
-                array[arrayIndex++] = item;
-        }
-
-        bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item)
-        {
-            var del = new DelInfo<TKey, TValue>(item.Value);
-            return Delete(item.Key, ref del);
-        }
-
-        #endregion
-
-        #region IEnumerator<KeyValuePair<TKey, TValue>>
-
-        private bool MoveNext(ref EnumState state)
-        {
-            if (_entries == null) throw new ObjectDisposedException(GetType().Name);
-
-            if (state.Current > 0)
-                state.Current = state.Next;
-
-            if (state.Current > 0)
-            {
-                state.Next = _entries[state.Current >> _shift][state.Current & _shiftMask].Link;
-                return true;
-            }
-
-            state.Unlock();
-            while (++state.Bucket < _hsize)
-            {
-                if (_buckets[state.Bucket] == 0)
-                    continue;
-
-                state.Lock(_locks[state.Bucket % _lsize]);
-
-                state.Current = _buckets[state.Bucket];
-                if (state.Current > 0)
-                {
-                    state.Next = _entries[state.Current >> _shift][state.Current & _shiftMask].Link;
-                    return true;
-                }
-
-                state.Unlock();
-            }
-
-            return false;
-        }
-
-        /// <summary>
-        /// Provides an enumerator that iterates through the collection.
-        /// </summary>
-        public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
-        {
-            private readonly LurchTable<TKey, TValue> _owner;
-            private EnumState _state;
-
-            internal Enumerator(LurchTable<TKey, TValue> owner)
-            {
-                _owner = owner;
-                _state = new EnumState();
-                _state.Init();
-            }
-
-            /// <summary>
-            /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-            /// </summary>
-            public void Dispose()
-            {
-                _state.Unlock();
-            }
-
-            object IEnumerator.Current { get { return Current; } }
-
-            /// <summary>
-            /// Gets the element in the collection at the current position of the enumerator.
-            /// </summary>
-            public KeyValuePair<TKey, TValue> Current
-            {
-                get
-                {
-                    int index = _state.Current;
-                    if (index <= 0)
-                        throw new InvalidOperationException();
-                    if (_owner._entries == null)
-                        throw new ObjectDisposedException(GetType().Name);
-
-                    return new KeyValuePair<TKey, TValue>
-                        (
-                            _owner._entries[index >> _owner._shift][index & _owner._shiftMask].Key,
-                            _owner._entries[index >> _owner._shift][index & _owner._shiftMask].Value
-                        );
-                }
-            }
-
-            /// <summary>
-            /// Advances the enumerator to the next element of the collection.
-            /// </summary>
-            public bool MoveNext()
-            {
-                return _owner.MoveNext(ref _state);
-            }
-
-            /// <summary>
-            /// Sets the enumerator to its initial position, which is before the first element in the collection.
-            /// </summary>
-            public void Reset()
-            {
-                _state.Unlock();
-                _state.Init();
-            }
-        }
-
-        /// <summary>
-        /// Returns an enumerator that iterates through the collection.
-        /// </summary>
-        public Enumerator GetEnumerator() { return new Enumerator(this); }
-        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
-        { return GetEnumerator(); }
-        IEnumerator IEnumerable.GetEnumerator()
-        { return GetEnumerator(); }
-        #endregion
-
-        #region KeyCollection
-        /// <summary>
-        /// Provides the collection of Keys for the LurchTable
-        /// </summary>
-        public class KeyCollection : ICollection<TKey>
-        {
-            private readonly LurchTable<TKey, TValue> _owner;
-
-            internal KeyCollection(LurchTable<TKey, TValue> owner)
-            {
-                _owner = owner;
-            }
-
-            #region ICollection<TKey> Members
-
-            /// <summary>
-            /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
-            /// </summary>
-            public bool Contains(TKey item)
-            {
-                return _owner.ContainsKey(item);
-            }
-
-            /// <summary>
-            /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
-            /// </summary>
-            public void CopyTo(TKey[] array, int arrayIndex)
-            {
-                foreach (var item in _owner)
-                    array[arrayIndex++] = item.Key;
-            }
-
-            /// <summary>
-            /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
-            /// </summary>
-            public int Count
-            {
-                get { return _owner.Count; }
-            }
-
-            /// <summary>
-            /// Returns an enumerator that iterates through the collection.
-            /// </summary>
-            public Enumerator GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-
-            /// <summary>
-            /// Provides an enumerator that iterates through the collection.
-            /// </summary>
-            public struct Enumerator : IEnumerator<TKey>
-            {
-                private readonly LurchTable<TKey, TValue> _owner;
-                private EnumState _state;
-
-                internal Enumerator(LurchTable<TKey, TValue> owner)
-                {
-                    _owner = owner;
-                    _state = new EnumState();
-                    _state.Init();
-                }
-
-                /// <summary>
-                /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-                /// </summary>
-                public void Dispose()
-                {
-                    _state.Unlock();
-                }
-
-                object IEnumerator.Current { get { return Current; } }
-
-                /// <summary>
-                /// Gets the element in the collection at the current position of the enumerator.
-                /// </summary>
-                public TKey Current
-                {
-                    get
-                    {
-                        int index = _state.Current;
-                        if (index <= 0)
-                            throw new InvalidOperationException();
-                        if (_owner._entries == null)
-                            throw new ObjectDisposedException(GetType().Name);
-                        return _owner._entries[index >> _owner._shift][index & _owner._shiftMask].Key;
-                    }
-                }
-
-                /// <summary>
-                /// Advances the enumerator to the next element of the collection.
-                /// </summary>
-                public bool MoveNext()
-                {
-                    return _owner.MoveNext(ref _state);
-                }
-
-                /// <summary>
-                /// Sets the enumerator to its initial position, which is before the first element in the collection.
-                /// </summary>
-                public void Reset()
-                {
-                    _state.Unlock();
-                    _state.Init();
-                }
-            }
-            [Obsolete]
-            IEnumerator<TKey> IEnumerable<TKey>.GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-            [Obsolete]
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-            [Obsolete]
-            bool ICollection<TKey>.IsReadOnly
-            {
-                get { return true; }
-            }
-            [Obsolete]
-            void ICollection<TKey>.Add(TKey item)
-            {
-                throw new NotSupportedException();
-            }
-            [Obsolete]
-            void ICollection<TKey>.Clear()
-            {
-                throw new NotSupportedException();
-            }
-            [Obsolete]
-            bool ICollection<TKey>.Remove(TKey item)
-            {
-                throw new NotSupportedException();
-            }
-
-            #endregion
-        }
-
-        private KeyCollection _keyCollection;
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        public KeyCollection Keys { get { return _keyCollection ?? (_keyCollection = new KeyCollection(this)); } }
-        [Obsolete]
-        ICollection<TKey> IDictionary<TKey, TValue>.Keys { get { return Keys; } }
-        #endregion
-
-        #region ValueCollection
-        /// <summary>
-        /// Provides the collection of Values for the LurchTable
-        /// </summary>
-        public class ValueCollection : ICollection<TValue>
-        {
-            private readonly LurchTable<TKey, TValue> _owner;
-
-            internal ValueCollection(LurchTable<TKey, TValue> owner)
-            {
-                _owner = owner;
-            }
-
-            #region ICollection<TValue> Members
-
-            /// <summary>
-            /// Determines whether the <see cref="T:System.Collections.Generic.ICollection`1"/> contains a specific value.
-            /// </summary>
-            public bool Contains(TValue value)
-            {
-                var comparer = EqualityComparer<TValue>.Default;
-                foreach (var item in _owner)
-                {
-                    if (comparer.Equals(item.Value, value))
-                        return true;
-                }
-                return false;
-            }
-
-            /// <summary>
-            /// Copies the elements of the <see cref="T:System.Collections.Generic.ICollection`1"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
-            /// </summary>
-            public void CopyTo(TValue[] array, int arrayIndex)
-            {
-                foreach (var item in _owner)
-                    array[arrayIndex++] = item.Value;
-            }
-
-            /// <summary>
-            /// Gets the number of elements contained in the <see cref="T:System.Collections.Generic.ICollection`1"/>.
-            /// </summary>
-            public int Count
-            {
-                get { return _owner.Count; }
-            }
-
-            /// <summary>
-            /// Returns an enumerator that iterates through the collection.
-            /// </summary>
-            public Enumerator GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-
-            /// <summary>
-            /// Provides an enumerator that iterates through the collection.
-            /// </summary>
-            public struct Enumerator : IEnumerator<TValue>
-            {
-                private readonly LurchTable<TKey, TValue> _owner;
-                private EnumState _state;
-
-                internal Enumerator(LurchTable<TKey, TValue> owner)
-                {
-                    _owner = owner;
-                    _state = new EnumState();
-                    _state.Init();
-                }
-
-                /// <summary>
-                /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
-                /// </summary>
-                public void Dispose()
-                {
-                    _state.Unlock();
-                }
-
-                object IEnumerator.Current { get { return Current; } }
-
-                /// <summary>
-                /// Gets the element in the collection at the current position of the enumerator.
-                /// </summary>
-                public TValue Current
-                {
-                    get
-                    {
-                        int index = _state.Current;
-                        if (index <= 0)
-                            throw new InvalidOperationException();
-                        if (_owner._entries == null)
-                            throw new ObjectDisposedException(GetType().Name);
-                        return _owner._entries[index >> _owner._shift][index & _owner._shiftMask].Value;
-                    }
-                }
-
-                /// <summary>
-                /// Advances the enumerator to the next element of the collection.
-                /// </summary>
-                public bool MoveNext()
-                {
-                    return _owner.MoveNext(ref _state);
-                }
-
-                /// <summary>
-                /// Sets the enumerator to its initial position, which is before the first element in the collection.
-                /// </summary>
-                public void Reset()
-                {
-                    _state.Unlock();
-                    _state.Init();
-                }
-            }
-            [Obsolete]
-            IEnumerator<TValue> IEnumerable<TValue>.GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-            [Obsolete]
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return new Enumerator(_owner);
-            }
-            [Obsolete]
-            bool ICollection<TValue>.IsReadOnly
-            {
-                get { return true; }
-            }
-            [Obsolete]
-            void ICollection<TValue>.Add(TValue item)
-            {
-                throw new NotSupportedException();
-            }
-            [Obsolete]
-            void ICollection<TValue>.Clear()
-            {
-                throw new NotSupportedException();
-            }
-            [Obsolete]
-            bool ICollection<TValue>.Remove(TValue item)
-            {
-                throw new NotSupportedException();
-            }
-
-            #endregion
-        }
-
-        private ValueCollection _valueCollection;
-        /// <summary>
-        /// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
-        /// </summary>
-        public ValueCollection Values { get { return _valueCollection ?? (_valueCollection = new ValueCollection(this)); } }
-        [Obsolete]
-        ICollection<TValue> IDictionary<TKey, TValue>.Values { get { return Values; } }
-
-        #endregion
-
-        #region Peek/Dequeue
-
-        /// <summary>
-        /// Retrieves the oldest entry in the collection based on the ordering supplied to the constructor.
-        /// </summary>
-        /// <returns>True if the out parameter value was set.</returns>
-        /// <exception cref="System.InvalidOperationException">Raised if the table is unordered</exception>
-        public bool Peek(out KeyValuePair<TKey, TValue> value)
-        {
-            if (_ordering == LurchTableOrder.None)
-                throw new InvalidOperationException();
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            while (true)
-            {
-                int index = Interlocked.CompareExchange(ref _entries[0][0].Prev, 0, 0);
-                if (index == 0)
-                {
-                    value = default(KeyValuePair<TKey, TValue>);
-                    return false;
-                }
-
-                int hash = _entries[index >> _shift][index & _shiftMask].Hash;
-                if (hash >= 0)
-                {
-                    int bucket = hash % _hsize;
-                    lock (_locks[bucket % _lsize])
-                    {
-                        if (index == _entries[0][0].Prev &&
-                            hash == _entries[index >> _shift][index & _shiftMask].Hash)
-                        {
-                            value = new KeyValuePair<TKey, TValue>(
-                                _entries[index >> _shift][index & _shiftMask].Key,
-                                _entries[index >> _shift][index & _shiftMask].Value
-                            );
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Removes the oldest entry in the collection based on the ordering supplied to the constructor.
-        /// If an item is not available a busy-wait loop is used to wait for for an item.
-        /// </summary>
-        /// <returns>The Key/Value pair removed.</returns>
-        /// <exception cref="System.InvalidOperationException">Raised if the table is unordered</exception>
-        public KeyValuePair<TKey, TValue> Dequeue()
-        {
-            if (_ordering == LurchTableOrder.None)
-                throw new InvalidOperationException();
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            KeyValuePair<TKey, TValue> value;
-            while (!TryDequeue(out value))
-            {
-                while (0 == Interlocked.CompareExchange(ref _entries[0][0].Prev, 0, 0))
-                    Thread.Sleep(0);
-            }
-            return value;
-        }
-
-        /// <summary>
-        /// Removes the oldest entry in the collection based on the ordering supplied to the constructor.
-        /// </summary>
-        /// <returns>False if no item was available</returns>
-        /// <exception cref="System.InvalidOperationException">Raised if the table is unordered</exception>
-        public bool TryDequeue(out KeyValuePair<TKey, TValue> value)
-        {
-            return TryDequeue(null, out value);
-        }
-
-        /// <summary>
-        /// Removes the oldest entry in the collection based on the ordering supplied to the constructor.
-        /// </summary>
-        /// <returns>False if no item was available</returns>
-        /// <exception cref="System.InvalidOperationException">Raised if the table is unordered</exception>
-        public bool TryDequeue(Predicate<KeyValuePair<TKey, TValue>> predicate, out KeyValuePair<TKey, TValue> value)
-        {
-            if (_ordering == LurchTableOrder.None)
-                throw new InvalidOperationException();
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            while (true)
-            {
-                int index = Interlocked.CompareExchange(ref _entries[0][0].Prev, 0, 0);
-                if (index == 0)
-                {
-                    value = default(KeyValuePair<TKey, TValue>);
-                    return false;
-                }
-
-                int hash = _entries[index >> _shift][index & _shiftMask].Hash;
-                if (hash >= 0)
-                {
-                    int bucket = hash % _hsize;
-                    lock (_locks[bucket % _lsize])
-                    {
-                        if (index == _entries[0][0].Prev &&
-                            hash == _entries[index >> _shift][index & _shiftMask].Hash)
-                        {
-                            if (predicate != null)
-                            {
-                                var item = new KeyValuePair<TKey, TValue>(
-                                    _entries[index >> _shift][index & _shiftMask].Key,
-                                    _entries[index >> _shift][index & _shiftMask].Value
-                                );
-                                if (!predicate(item))
-                                {
-                                    value = item;
-                                    return false;
-                                }
-                            }
-
-                            int next = _entries[index >> _shift][index & _shiftMask].Link;
-                            bool removed = false;
-
-                            if (_buckets[bucket] == index)
-                            {
-                                _buckets[bucket] = next;
-                                removed = true;
-                            }
-                            else
-                            {
-                                int test = _buckets[bucket];
-                                while (test != 0)
-                                {
-                                    int cmp = _entries[test >> _shift][test & _shiftMask].Link;
-                                    if (cmp == index)
-                                    {
-                                        _entries[test >> _shift][test & _shiftMask].Link = next;
-                                        removed = true;
-                                        break;
-                                    }
-                                    test = cmp;
-                                }
-                            }
-                            if (!removed)
-                                throw new LurchTableCorruptionException();
-
-                            value = new KeyValuePair<TKey, TValue>(
-                                _entries[index >> _shift][index & _shiftMask].Key,
-                                _entries[index >> _shift][index & _shiftMask].Value
-                            );
-                            Interlocked.Decrement(ref _count);
-                            if (_ordering != LurchTableOrder.None)
-                                InternalUnlink(index);
-                            FreeSlot(ref index, Interlocked.Increment(ref _freeVersion));
-
-                            var handler = ItemRemoved;
-                            if (handler != null)
-                                handler(value);
-
-                            return true;
-                        }
-                    }
-                }
-            }
-        }
-
-        #endregion
-
-        #region Internal Implementation
-
-        enum InsertResult { Inserted = 1, Updated = 2, Exists = 3, NotFound = 4 }
-
-        bool InternalGetValue(int hash, TKey key, out TValue value)
-        {
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            int bucket = hash % _hsize;
-            lock (_locks[bucket % _lsize])
-            {
-                int index = _buckets[bucket];
-                while (index != 0)
-                {
-                    if (hash == _entries[index >> _shift][index & _shiftMask].Hash &&
-                        _comparer.Equals(key, _entries[index >> _shift][index & _shiftMask].Key))
-                    {
-                        value = _entries[index >> _shift][index & _shiftMask].Value;
-                        if (hash == _entries[index >> _shift][index & _shiftMask].Hash)
-                        {
-                            if (_ordering == LurchTableOrder.Access)
-                            {
-                                InternalUnlink(index);
-                                InternalLink(index);
-                            }
-                            return true;
-                        }
-                    }
-                    index = _entries[index >> _shift][index & _shiftMask].Link;
-                }
-
-                value = default(TValue);
-                return false;
-            }
-        }
-
-        InsertResult Insert<T>(TKey key, ref T value) where T : ICreateOrUpdateValue<TKey, TValue>
-        {
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            int hash = _comparer.GetHashCode(key) & int.MaxValue;
-            int added;
-
-            InsertResult result = InternalInsert(hash, key, out added, ref value);
-
-            if (added > _limit && _ordering != LurchTableOrder.None)
-            {
-                KeyValuePair<TKey, TValue> ignore;
-                TryDequeue(out ignore);
-            }
-            return result;
-        }
-
-        InsertResult InternalInsert<T>(int hash, TKey key, out int added, ref T value) where T : ICreateOrUpdateValue<TKey, TValue>
-        {
-            int bucket = hash % _hsize;
-            lock (_locks[bucket % _lsize])
-            {
-                TValue temp;
-                int index = _buckets[bucket];
-                while (index != 0)
-                {
-                    if (hash == _entries[index >> _shift][index & _shiftMask].Hash &&
-                        _comparer.Equals(key, _entries[index >> _shift][index & _shiftMask].Key))
-                    {
-                        temp = _entries[index >> _shift][index & _shiftMask].Value;
-                        var original = temp;
-                        if (value.UpdateValue(key, ref temp))
-                        {
-                            _entries[index >> _shift][index & _shiftMask].Value = temp;
-
-                            if (_ordering == LurchTableOrder.Modified || _ordering == LurchTableOrder.Access)
-                            {
-                                InternalUnlink(index);
-                                InternalLink(index);
-                            }
-
-                            var handler = ItemUpdated;
-                            if (handler != null)
-                                handler(new KeyValuePair<TKey, TValue>(key, original), new KeyValuePair<TKey, TValue>(key, temp));
-
-                            added = -1;
-                            return InsertResult.Updated;
-                        }
-
-                        added = -1;
-                        return InsertResult.Exists;
-                    }
-                    index = _entries[index >> _shift][index & _shiftMask].Link;
-                }
-                if (value.CreateValue(key, out temp))
-                {
-#pragma warning disable 612,618
-                    index = AllocSlot();
-#pragma warning restore 612,618
-                    _entries[index >> _shift][index & _shiftMask].Hash = hash;
-                    _entries[index >> _shift][index & _shiftMask].Key = key;
-                    _entries[index >> _shift][index & _shiftMask].Value = temp;
-                    _entries[index >> _shift][index & _shiftMask].Link = _buckets[bucket];
-                    _buckets[bucket] = index;
-
-                    added = Interlocked.Increment(ref _count);
-                    if (_ordering != LurchTableOrder.None)
-                        InternalLink(index);
-
-                    var handler = ItemAdded;
-                    if (handler != null)
-                        handler(new KeyValuePair<TKey, TValue>(key, temp));
-
-                    return InsertResult.Inserted;
-                }
-            }
-
-            added = -1;
-            return InsertResult.NotFound;
-        }
-
-        bool Delete<T>(TKey key, ref T value) where T : IRemoveValue<TKey, TValue>
-        {
-            if (_entries == null)
-                throw new ObjectDisposedException(GetType().Name);
-
-            int hash = _comparer.GetHashCode(key) & int.MaxValue;
-            int bucket = hash % _hsize;
-            lock (_locks[bucket % _lsize])
-            {
-                int prev = 0;
-                int index = _buckets[bucket];
-                while (index != 0)
-                {
-                    if (hash == _entries[index >> _shift][index & _shiftMask].Hash &&
-                        _comparer.Equals(key, _entries[index >> _shift][index & _shiftMask].Key))
-                    {
-                        TValue temp = _entries[index >> _shift][index & _shiftMask].Value;
-
-                        if (value.RemoveValue(key, temp))
-                        {
-                            int next = _entries[index >> _shift][index & _shiftMask].Link;
-                            if (prev == 0)
-                                _buckets[bucket] = next;
-                            else
-                                _entries[prev >> _shift][prev & _shiftMask].Link = next;
-
-                            Interlocked.Decrement(ref _count);
-                            if (_ordering != LurchTableOrder.None)
-                                InternalUnlink(index);
-                            FreeSlot(ref index, Interlocked.Increment(ref _freeVersion));
-
-                            var handler = ItemRemoved;
-                            if (handler != null)
-                                handler(new KeyValuePair<TKey, TValue>(key, temp));
-
-                            return true;
-                        }
-                        return false;
-                    }
-
-                    prev = index;
-                    index = _entries[index >> _shift][index & _shiftMask].Link;
-                }
-            }
-            return false;
-        }
-
-        void InternalLink(int index)
-        {
-            Interlocked.Exchange(ref _entries[index >> _shift][index & _shiftMask].Prev, 0);
-            Interlocked.Exchange(ref _entries[index >> _shift][index & _shiftMask].Next, ~0);
-            int next = Interlocked.Exchange(ref _entries[0][0].Next, index);
-            if (next < 0)
-                throw new LurchTableCorruptionException();
-
-            while (0 != Interlocked.CompareExchange(ref _entries[next >> _shift][next & _shiftMask].Prev, index, 0))
-            { }
-
-            Interlocked.Exchange(ref _entries[index >> _shift][index & _shiftMask].Next, next);
-        }
-
-        void InternalUnlink(int index)
-        {
-            while (true)
-            {
-                int cmp;
-                int prev = _entries[index >> _shift][index & _shiftMask].Prev;
-                while (prev >= 0 && prev != (cmp = Interlocked.CompareExchange(
-                            ref _entries[index >> _shift][index & _shiftMask].Prev, ~prev, prev)))
-                    prev = cmp;
-                if (prev < 0)
-                    throw new LurchTableCorruptionException();
-
-                int next = _entries[index >> _shift][index & _shiftMask].Next;
-                while (next >= 0 && next != (cmp = Interlocked.CompareExchange(
-                            ref _entries[index >> _shift][index & _shiftMask].Next, ~next, next)))
-                    next = cmp;
-                if (next < 0)
-                    throw new LurchTableCorruptionException();
-
-                if ((Interlocked.CompareExchange(
-                        ref _entries[prev >> _shift][prev & _shiftMask].Next, next, index) == index))
-                {
-                    while (Interlocked.CompareExchange(
-                               ref _entries[next >> _shift][next & _shiftMask].Prev, prev, index) != index)
-                    { }
-                    return;
-                }
-
-                //cancel the delete markers and retry
-                if (~next != Interlocked.CompareExchange(
-                        ref _entries[index >> _shift][index & _shiftMask].Next, next, ~next))
-                    throw new LurchTableCorruptionException();
-                if (~prev != Interlocked.CompareExchange(
-                        ref _entries[index >> _shift][index & _shiftMask].Prev, prev, ~prev))
-                    throw new LurchTableCorruptionException();
-            }
-        }
-
-        [Obsolete("Release build inlining, so we need to ignore for testing.")]
-        int AllocSlot()
-        {
-            while (true)
-            {
-                int allocated = _entries.Length * _allocSize;
-                var previous = _entries;
-
-                while (_count + OverAlloc < allocated || _used < allocated)
-                {
-                    int next;
-                    if (_count + FreeSlots < _used)
-                    {
-                        int freeSlotIndex = Interlocked.Increment(ref _allocNext);
-                        int slot = (freeSlotIndex & int.MaxValue) % FreeSlots;
-                        next = Interlocked.Exchange(ref _free[slot].Head, 0);
-                        if (next != 0)
-                        {
-                            int nextFree = _entries[next >> _shift][next & _shiftMask].Link;
-                            if (nextFree == 0)
-                            {
-                                Interlocked.Exchange(ref _free[slot].Head, next);
-                            }
-                            else
-                            {
-                                Interlocked.Exchange(ref _free[slot].Head, nextFree);
-                                return next;
-                            }
-                        }
-                    }
-
-                    next = _used;
-                    if (next < allocated)
-                    {
-                        int alloc = Interlocked.CompareExchange(ref _used, next + 1, next);
-                        if (alloc == next)
-                        {
-                            return next;
-                        }
-                    }
-                }
-
-                lock (this)
-                {
-                    //time to grow...
-                    if (ReferenceEquals(_entries, previous))
-                    {
-                        Entry[][] arentries = new Entry[_entries.Length + 1][];
-                        _entries.CopyTo(arentries, 0);
-                        arentries[arentries.Length - 1] = new Entry[_allocSize];
-
-                        Interlocked.CompareExchange(ref _entries, arentries, previous);
-                    }
-                }
-            }
-        }
-
-        void FreeSlot(ref int index, int ver)
-        {
-            _entries[index >> _shift][index & _shiftMask].Key = default(TKey);
-            _entries[index >> _shift][index & _shiftMask].Value = default(TValue);
-            Interlocked.Exchange(ref _entries[index >> _shift][index & _shiftMask].Link, 0);
-
-            int slot = (ver & int.MaxValue) % FreeSlots;
-            int prev = Interlocked.Exchange(ref _free[slot].Tail, index);
-
-            if (prev <= 0 || 0 != Interlocked.CompareExchange(ref _entries[prev >> _shift][prev & _shiftMask].Link, index, 0))
-            {
-                throw new LurchTableCorruptionException();
-            }
-        }
-
-        #endregion
-
-        #region Internal Structures
-
-        struct FreeList
-        {
-            public int Head;
-            public int Tail;
-        }
-
-        struct Entry
-        {
-            public int Prev, Next; // insertion/access sequence ordering
-            public int Link;
-            public int Hash; // hash value of entry's Key
-            public TKey Key; // key of entry
-            public TValue Value; // value of entry
-        }
-
-        struct EnumState
-        {
-            private object _locked;
-            public int Bucket, Current, Next;
-            public void Init()
-            {
-                Bucket = -1;
-                Current = 0;
-                Next = 0;
-                _locked = null;
-            }
-
-            public void Unlock()
-            {
-                if (_locked != null)
-                {
-                    Monitor.Exit(_locked);
-                    _locked = null;
-                }
-            }
-
-            public void Lock(object lck)
-            {
-                if (_locked != null)
-                    Monitor.Exit(_locked);
-                Monitor.Enter(_locked = lck);
-            }
-        }
-
-        #endregion
-    }
-
-    #region LurchTable Support
-
-    #region Internal Structures (de-nested)
-
-    // LUCENENET NOTE: These were originally nested within LurchTable, but
-    // using nested generic structs without explicitly defining their parameters
-    // fails on Xamarin.iOS because of incomplete generics support. Therefore,
-    // we de-nested them and moved them here. See: LUCENENET-602
-
-    struct DelInfo<TKey, TValue> : IRemoveValue<TKey, TValue>
-    {
-        public TValue Value;
-        readonly bool _hasTestValue;
-        readonly TValue _testValue;
-        public KeyValuePredicate<TKey, TValue> Condition;
-
-        public DelInfo(TValue expected)
-        {
-            Value = default(TValue);
-            _testValue = expected;
-            _hasTestValue = true;
-            Condition = null;
-        }
-
-        public bool RemoveValue(TKey key, TValue value)
-        {
-            Value = value;
-
-            if (_hasTestValue && !EqualityComparer<TValue>.Default.Equals(_testValue, value))
-                return false;
-            if (Condition != null && !Condition(key, value))
-                return false;
-
-            return true;
-        }
-    }
-
-    struct AddInfo<TKey, TValue> : ICreateOrUpdateValue<TKey, TValue>
-    {
-        public bool CanUpdate;
-        public TValue Value;
-        public bool CreateValue(TKey key, out TValue value)
-        {
-            value = Value;
-            return true;
-        }
-
-        public bool UpdateValue(TKey key, ref TValue value)
-        {
-            if (!CanUpdate)
-            {
-                Value = value;
-                return false;
-            }
-
-            value = Value;
-            return true;
-        }
-    }
-
-    struct Add2Info<TKey, TValue> : ICreateOrUpdateValue<TKey, TValue>
-    {
-        readonly bool _hasAddValue;
-        readonly TValue _addValue;
-        public TValue Value;
-        public Func<TKey, TValue> Create;
-        public KeyValueUpdate<TKey, TValue> Update;
-
-        public Add2Info(TValue addValue) : this()
-        {
-            _hasAddValue = true;
-            _addValue = addValue;
-        }
-
-        public bool CreateValue(TKey key, out TValue value)
-        {
-            if (_hasAddValue)
-            {
-                value = Value = _addValue;
-                return true;
-            }
-            if (Create != null)
-            {
-                value = Value = Create(key);
-                return true;
-            }
-            value = Value = default(TValue);
-            return false;
-        }
-
-        public bool UpdateValue(TKey key, ref TValue value)
-        {
-            if (Update == null)
-            {
-                Value = value;
-                return false;
-            }
-
-            value = Value = Update(key, value);
-            return true;
-        }
-    }
-
-    struct UpdateInfo<TKey, TValue> : ICreateOrUpdateValue<TKey, TValue>
-    {
-        public TValue Value;
-        readonly bool _hasTestValue;
-        readonly TValue _testValue;
-
-        public UpdateInfo(TValue expected)
-        {
-            Value = default(TValue);
-            _testValue = expected;
-            _hasTestValue = true;
-        }
-
-        bool ICreateValue<TKey, TValue>.CreateValue(TKey key, out TValue value)
-        {
-            value = default(TValue);
-            return false;
-        }
-        public bool UpdateValue(TKey key, ref TValue value)
-        {
-            if (_hasTestValue && !EqualityComparer<TValue>.Default.Equals(_testValue, value))
-                return false;
-
-            value = Value;
-            return true;
-        }
-    }
-
-    #endregion
-
-    #region Exceptions
-
-    /// <summary>
-    /// Exception class: LurchTableCorruptionException
-    /// The LurchTable internal datastructure appears to be corrupted.
-    /// </summary>
-#if FEATURE_SERIALIZABLE
-    [System.SerializableAttribute()]
-#endif
-    [global::System.Diagnostics.DebuggerStepThroughAttribute()]
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("CSharpTest.Net.Generators", "2.13.222.435")]
-    public partial class LurchTableCorruptionException : Exception
-    {
-#if FEATURE_SERIALIZABLE
-        /// <summary>
-        /// Serialization constructor
-        /// </summary>
-        protected LurchTableCorruptionException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : base(info, context)
-        {
-        }
-#endif
-        /// <summary>
-        /// Used to create this exception from an hresult and message bypassing the message formatting
-        /// </summary>
-        internal static System.Exception Create(int hResult, string message)
-        {
-            return new LurchTableCorruptionException((System.Exception)null, hResult, message);
-        }
-        /// <summary>
-        /// Constructs the exception from an hresult and message bypassing the message formatting
-        /// </summary>
-        protected LurchTableCorruptionException(System.Exception innerException, int hResult, string message) : base(message, innerException)
-        {
-            base.HResult = hResult;
-        }
-        /// <summary>
-        /// The LurchTable internal datastructure appears to be corrupted.
-        /// </summary>
-        public LurchTableCorruptionException()
-            : this((System.Exception)null, -1, "The LurchTable internal datastructure appears to be corrupted.")
-        {
-        }
-        /// <summary>
-        /// The LurchTable internal datastructure appears to be corrupted.
-        /// </summary>
-        public LurchTableCorruptionException(System.Exception innerException)
-            : this(innerException, -1, "The LurchTable internal datastructure appears to be corrupted.")
-        {
-        }
-        /// <summary>
-        /// if(condition == false) throws The LurchTable internal datastructure appears to be corrupted.
-        /// </summary>
-        public static void Assert(bool condition)
-        {
-            if (!condition) throw new LurchTableCorruptionException();
-        }
-    }
-
-#endregion // Exceptions
-
-#region Delegates
-
-    /// <summary> Provides a delegate that performs an atomic update of a key/value pair </summary>
-    public delegate TValue KeyValueUpdate<TKey, TValue>(TKey key, TValue original);
-
-    /// <summary> Provides a delegate that performs a test on key/value pair </summary>
-    public delegate bool KeyValuePredicate<TKey, TValue>(TKey key, TValue original);
-
-#endregion // Delegates
-
-#region Interfaces
-
-    /// <summary>
-    /// An interface to provide conditional or custom creation logic to a concurrent dictionary.
-    /// </summary>
-    public interface ICreateValue<TKey, TValue>
-    {
-        /// <summary>
-        /// Called when the key was not found within the dictionary to produce a new value that can be added.
-        /// Return true to continue with the insertion, or false to prevent the key/value from being inserted.
-        /// </summary>
-        bool CreateValue(TKey key, out TValue value);
-    }
-    /// <summary>
-    /// An interface to provide conditional or custom update logic to a concurrent dictionary.
-    /// </summary>
-    public interface IUpdateValue<TKey, TValue>
-    {
-        /// <summary>
-        /// Called when the key was found within the dictionary to produce a modified value to update the item
-        /// to. Return true to continue with the update, or false to prevent the key/value from being updated.
-        /// </summary>
-        bool UpdateValue(TKey key, ref TValue value);
-    }
-    /// <summary>
-    /// An interface to provide conditional or custom creation or update logic to a concurrent dictionary.
-    /// </summary>
-    /// <remarks>
-    /// Generally implemented as a struct and passed by ref to save stack space and to retrieve the values
-    /// that where inserted or updated.
-    /// </remarks>
-    public interface ICreateOrUpdateValue<TKey, TValue> : ICreateValue<TKey, TValue>, IUpdateValue<TKey, TValue>
-    {
-    }
-
-    /// <summary>
-    /// An interface to provide conditional removal of an item from a concurrent dictionary.
-    /// </summary>
-    /// <remarks>
-    /// Generally implemented as a struct and passed by ref to save stack space and to retrieve the values
-    /// that where inserted or updated.
-    /// </remarks>
-    public interface IRemoveValue<TKey, TValue>
-    {
-        /// <summary>
-        /// Called when the dictionary is about to remove the key/value pair provided, return true to allow
-        /// it's removal, or false to prevent it from being removed.
-        /// </summary>
-        bool RemoveValue(TKey key, TValue value);
-    }
-
-#endregion // interfaces
-
-#region Classes
-
-    internal class HashUtilities
-    {
-        private static readonly int[] PrimeNumbers =
-            new[]
-                {
-                    17, 37, 67, 131, 257, 521, // ROK - Added smaller primes
-                    1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591,
-                    17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437,
-                    187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403, 968897, 1162687,
-                    1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287, 4999559, 5999471, 7199369
-                };
-
-        internal static int SelectPrimeNumber(int hashSize)
-        {
-            int offset = Array.BinarySearch(PrimeNumbers, hashSize);
-            if (offset < 0)
-                offset = ~offset;
-            return PrimeNumbers[Math.Min(offset, PrimeNumbers.Length - 1)];
-        }
-    }
-
-#endregion // Classes
-
-#endregion // LurchTable Support
-}