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 2017/03/21 21:25:57 UTC
[5/9] lucenenet git commit: BUG:
Lucene.Net.Core.Util.WeakIdentityMap: Added fix for WeakIdentityMap and
TestWeakIdentityMap provided by Vincent Van Den Berghe
BUG: Lucene.Net.Core.Util.WeakIdentityMap: Added fix for WeakIdentityMap and TestWeakIdentityMap provided by Vincent Van Den Berghe
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/74e166f6
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/74e166f6
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/74e166f6
Branch: refs/heads/api-work
Commit: 74e166f626464253439291600238bea8b55c07d0
Parents: e8bf549
Author: Shad Storhaug <sh...@shadstorhaug.com>
Authored: Tue Mar 21 23:55:24 2017 +0700
Committer: Shad Storhaug <sh...@shadstorhaug.com>
Committed: Tue Mar 21 23:55:24 2017 +0700
----------------------------------------------------------------------
src/Lucene.Net.Core/Util/WeakIdentityMap.cs | 119 ++++++++-----------
.../Util/TestWeakIdentityMap.cs | 40 ++++---
2 files changed, 72 insertions(+), 87 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/74e166f6/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
index c6c35c4..2999d94 100644
--- a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
+++ b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
@@ -1,29 +1,27 @@
-using Lucene.Net.Support;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Linq;
using System.Runtime.CompilerServices;
using System.Collections;
namespace Lucene.Net.Util
{
/*
- * 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.
- */
+ * 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.
+ */
/// <summary>
/// Implements a combination of <seealso cref="java.util.WeakHashMap"/> and
@@ -61,9 +59,8 @@ namespace Lucene.Net.Util
/// @lucene.internal
/// </summary>
public sealed class WeakIdentityMap<TKey, TValue>
- where TKey : class
+ where TKey : class
{
- //private readonly ReferenceQueue<object> queue = new ReferenceQueue<object>();
private readonly IDictionary<IdentityWeakReference, TValue> backingStore;
private readonly bool reapOnRead;
@@ -82,7 +79,7 @@ namespace Lucene.Net.Util
/// <param name="reapOnRead"> controls if the map <a href="#reapInfo">cleans up the reference queue on every read operation</a>. </param>
public static WeakIdentityMap<TKey, TValue> NewHashMap(bool reapOnRead)
{
- return new WeakIdentityMap<TKey, TValue>(new HashMap<IdentityWeakReference, TValue>(), reapOnRead);
+ return new WeakIdentityMap<TKey, TValue>(new Dictionary<IdentityWeakReference, TValue>(), reapOnRead);
}
/// <summary>
@@ -252,16 +249,17 @@ namespace Lucene.Net.Util
private class IteratorAnonymousInnerClassHelper : IEnumerator<TKey>
{
- private readonly WeakIdentityMap<TKey,TValue> outerInstance;
+ private readonly WeakIdentityMap<TKey, TValue> outerInstance;
+ private readonly IEnumerator<KeyValuePair<IdentityWeakReference, TValue>> enumerator;
- public IteratorAnonymousInnerClassHelper(WeakIdentityMap<TKey,TValue> outerInstance)
+ public IteratorAnonymousInnerClassHelper(WeakIdentityMap<TKey, TValue> outerInstance)
{
this.outerInstance = outerInstance;
+ enumerator = outerInstance.backingStore.GetEnumerator();
}
// holds strong reference to next element in backing iterator:
private object next = null;
- private int position = -1; // start before the beginning of the set
public TKey Current
{
@@ -279,56 +277,32 @@ namespace Lucene.Net.Util
}
}
+
public void Dispose()
{
- // Nothing to do
+ enumerator.Dispose();
}
-
+
public bool MoveNext()
{
- while (true)
+ while (enumerator.MoveNext())
{
- IdentityWeakReference key;
-
- // If the next position doesn't exist, exit
- if (++position >= outerInstance.backingStore.Count)
- {
- position--;
- return false;
- }
- try
+ next = enumerator.Current.Key.Target;
+ if (next != null)
{
- key = outerInstance.backingStore.Keys.ElementAt(position);
- }
- catch (ArgumentOutOfRangeException)
- {
- // some other thread beat us to the last element (or removed a prior element) - fail gracefully.
- position--;
- return false;
- }
- if (!key.IsAlive)
- {
- outerInstance.backingStore.Remove(key);
- position--;
- continue;
- }
- // unfold "null" special value:
- if (key.Target == NULL)
- {
- next = null;
- }
- else
- {
- next = key.Target;
+ // unfold "null" special value:
+ if (next == NULL)
+ next = null;
+ return true;
}
- return true;
}
+ return false;
}
public void Reset()
{
- throw new NotSupportedException();
+ enumerator.Reset();
}
}
@@ -354,22 +328,27 @@ namespace Lucene.Net.Util
/// collected key/value pairs from the map. Calling this method is not needed
/// if {@code reapOnRead = true}. Otherwise it might be a good idea
/// to call this method when there is spare time (e.g. from a background thread). </summary>
- /// <seealso cref= <a href="#reapInfo">Information about the <code>reapOnRead</code> setting</a> </seealso>
+ /// <seealso cref= <a href="#reapInfo">Information about the <code>reapOnRead</code> setting</a> </seealso>
public void Reap()
{
- List<IdentityWeakReference> keysToRemove = new List<IdentityWeakReference>();
- foreach (IdentityWeakReference zombie in backingStore.Keys)
+ List<IdentityWeakReference> keysToRemove = null;
+ foreach (var item in backingStore)
{
- if (!zombie.IsAlive)
+ if (!item.Key.IsAlive)
{
- keysToRemove.Add(zombie);
+ // create the list of keys to remove only if there are keys to remove.
+ // this reduces heap pressure
+ if (keysToRemove == null)
+ keysToRemove = new List<IdentityWeakReference>();
+ keysToRemove.Add(item.Key);
}
}
- foreach (var key in keysToRemove)
- {
- backingStore.Remove(key);
- }
+ if (keysToRemove != null)
+ foreach (var key in keysToRemove)
+ {
+ backingStore.Remove(key);
+ }
}
// we keep a hard reference to our NULL key, so map supports null keys that never get GCed:
@@ -396,9 +375,9 @@ namespace Lucene.Net.Util
{
return true;
}
- if (o is IdentityWeakReference)
+ IdentityWeakReference @ref = o as IdentityWeakReference;
+ if (@ref != null)
{
- IdentityWeakReference @ref = (IdentityWeakReference)o;
if (this.Target == @ref.Target)
{
return true;
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/74e166f6/src/Lucene.Net.Tests/Util/TestWeakIdentityMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/Util/TestWeakIdentityMap.cs b/src/Lucene.Net.Tests/Util/TestWeakIdentityMap.cs
index ac8cd70..48270e0 100644
--- a/src/Lucene.Net.Tests/Util/TestWeakIdentityMap.cs
+++ b/src/Lucene.Net.Tests/Util/TestWeakIdentityMap.cs
@@ -1,3 +1,4 @@
+using Lucene.Net.Attributes;
using Lucene.Net.Randomized.Generators;
using Lucene.Net.Support;
using NUnit.Framework;
@@ -56,11 +57,13 @@ namespace Lucene.Net.Util
// try null key & check its iterator also return null:
map.Put(null, "null");
{
- IEnumerator<string> iter = map.Keys.GetEnumerator();
- Assert.IsTrue(iter.MoveNext());
- Assert.IsNull(iter.Current);
- Assert.IsFalse(iter.MoveNext());
- Assert.IsFalse(iter.MoveNext());
+ using (IEnumerator<string> iter = map.Keys.GetEnumerator())
+ {
+ Assert.IsTrue(iter.MoveNext());
+ Assert.IsNull(iter.Current);
+ Assert.IsFalse(iter.MoveNext());
+ Assert.IsFalse(iter.MoveNext());
+ }
}
// 2 more keys:
map.Put(key1, "bar1");
@@ -105,10 +108,9 @@ namespace Lucene.Net.Util
Assert.AreEqual(3, map.Count);
int c = 0, keysAssigned = 0;
- for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();)
+ foreach (object k in map.Keys)
{
//Assert.IsTrue(iter.hasNext()); // try again, should return same result!
- string k = iter.Current;
// LUCENENET NOTE: Need object.ReferenceEquals here because the == operator does more than check reference equality
Assert.IsTrue(object.ReferenceEquals(k, key1) || object.ReferenceEquals(k, key2) | object.ReferenceEquals(k, key3));
keysAssigned += object.ReferenceEquals(k, key1) ? 1 : (object.ReferenceEquals(k, key2) ? 2 : 4);
@@ -143,9 +145,9 @@ namespace Lucene.Net.Util
size = newSize;
Thread.Sleep(TimeSpan.FromSeconds(1));
c = 0;
- for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();)
+ foreach (object k in map.Keys)
{
- Assert.IsNotNull(iter.Current);
+ Assert.IsNotNull(k);
c++;
}
newSize = map.Count;
@@ -166,8 +168,8 @@ namespace Lucene.Net.Util
Assert.AreEqual(0, map.Count);
Assert.IsTrue(map.IsEmpty);
- IEnumerator<string> it = map.Keys.GetEnumerator();
- Assert.IsFalse(it.MoveNext());
+ using (IEnumerator<string> it = map.Keys.GetEnumerator())
+ Assert.IsFalse(it.MoveNext());
/*try
{
it.Next();
@@ -194,7 +196,11 @@ namespace Lucene.Net.Util
Assert.IsTrue(map.IsEmpty);
}
- [Test]
+#if !NETSTANDARD
+ // LUCENENET: There is no Timeout on NUnit for .NET Core.
+ [Timeout(60000)]
+#endif
+ [Test, HasTimeout]
public virtual void TestConcurrentHashMap()
{
// don't make threadCount and keyCount random, otherwise easily OOMs or fails otherwise:
@@ -224,7 +230,7 @@ namespace Lucene.Net.Util
{
foreach (var w in workers)
{
- w.Join(1000L);
+ w.Join();
}
}
@@ -258,9 +264,9 @@ namespace Lucene.Net.Util
size = newSize;
Thread.Sleep(new TimeSpan(100L));
int c = 0;
- for (IEnumerator<object> it = map.Keys.GetEnumerator(); it.MoveNext();)
+ foreach (object k in map.Keys)
{
- Assert.IsNotNull(it.Current);
+ Assert.IsNotNull(k);
c++;
}
newSize = map.Count;
@@ -332,9 +338,9 @@ namespace Lucene.Net.Util
break;
case 4:
// check iterator still working
- for (IEnumerator<object> it = map.Keys.GetEnumerator(); it.MoveNext();)
+ foreach (object k in map.Keys)
{
- Assert.IsNotNull(it.Current);
+ Assert.IsNotNull(k);
}
break;
default: