lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From synhers...@apache.org
Subject [47/49] lucenenet git commit: Finished implementation of Core.Util.TestWeakIdenityMap and fixed some bugs with the enumerator logic of WeakIdenityMap (test still failing).
Date Sun, 02 Oct 2016 10:17:18 GMT
Finished implementation of Core.Util.TestWeakIdenityMap and fixed some bugs with the enumerator
logic of WeakIdenityMap (test still failing).


Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/e8b44e75
Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/e8b44e75
Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/e8b44e75

Branch: refs/heads/master
Commit: e8b44e751130bfe1e01489a7879e13eaf1090061
Parents: 44a5cb5
Author: Shad Storhaug <shad@shadstorhaug.com>
Authored: Sun Sep 18 05:25:09 2016 +0700
Committer: Shad Storhaug <shad@shadstorhaug.com>
Committed: Sun Sep 18 07:28:41 2016 +0700

----------------------------------------------------------------------
 src/Lucene.Net.Core/Util/WeakIdentityMap.cs     | 175 ++++++++++---------
 .../core/Util/TestWeakIdentityMap.cs            | 146 +++++++++-------
 2 files changed, 179 insertions(+), 142 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucenenet/blob/e8b44e75/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 aa4e1a8..7d2ce1c 100644
--- a/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
+++ b/src/Lucene.Net.Core/Util/WeakIdentityMap.cs
@@ -2,7 +2,9 @@ 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
 {
@@ -72,7 +74,7 @@ namespace Lucene.Net.Util
         /// Creates a new {@code WeakIdentityMap} based on a non-synchronized <seealso
cref="HashMap"/>.
         /// The map <a href="#reapInfo">cleans up the reference queue on every read
operation</a>.
         /// </summary>
-        public static WeakIdentityMap<K, V> newHashMap()
+        public static WeakIdentityMap<K, V> NewHashMap()
         {
             return NewHashMap(false);
         }
@@ -162,20 +164,37 @@ namespace Lucene.Net.Util
 
         public IEnumerable<K> Keys
         {
-            // .NET port: using this method which mimics IDictionary instead of KeyIterator()
             get
             {
-                foreach (var key in BackingStore.Keys)
-                {
-                    var target = key.Target;
+                return new KeyWrapper(this);
+            }
+        }
 
-                    if (target == null)
-                        continue;
-                    else if (target == NULL)
-                        yield return null;
-                    else
-                        yield return (K)target;
-                }
+        /// <summary>
+        /// LUCENENET specific class to allow the 
+        /// GetEnumerator() method to be overridden
+        /// for the keys so we can return an enumerator
+        /// that is smart enough to clean up the dead keys
+        /// and also so that MoveNext() returns false in the
+        /// event there are no more values left (instead of returning
+        /// a null value in an extra enumeration).
+        /// </summary>
+        private class KeyWrapper : IEnumerable<K>
+        {
+            private readonly WeakIdentityMap<K, V> outerInstance;
+            public KeyWrapper(WeakIdentityMap<K, V> outerInstance)
+            {
+                this.outerInstance = outerInstance;
+            }
+            public IEnumerator<K> GetEnumerator()
+            {
+                outerInstance.Reap();
+                return new IteratorAnonymousInnerClassHelper(outerInstance);
+            }
+
+            IEnumerator IEnumerable.GetEnumerator()
+            {
+                return GetEnumerator();
             }
         }
 
@@ -229,93 +248,87 @@ namespace Lucene.Net.Util
             return BackingStore.Count;
         }
 
-        /*LUCENE TO-DO I don't think necessary
-        /// <summary>
-        /// Returns an iterator over all weak keys of this map.
-        /// Keys already garbage collected will not be returned.
-        /// this Iterator does not support removals.
-        /// </summary>
-        public IEnumerator<K> KeyIterator()
-        {
-          Reap();
-          IEnumerator<IdentityWeakReference> iterator = BackingStore.Keys.GetEnumerator();
-          // IMPORTANT: Don't use oal.util.FilterIterator here:
-          // We need *strong* reference to current key after setNext()!!!
-          return new IteratorAnonymousInnerClassHelper(this, iterator);
-        }
-
-        private class IteratorAnonymousInnerClassHelper : Iterator<K>
+        private class IteratorAnonymousInnerClassHelper : IEnumerator<K>
         {
-            private readonly WeakIdentityMap<K,V> OuterInstance;
-
-            private IEnumerator<IdentityWeakReference> Iterator;
+            private readonly WeakIdentityMap<K,V> outerInstance;
 
-            public IteratorAnonymousInnerClassHelper(WeakIdentityMap<K,V> outerInstance,
IEnumerator<IdentityWeakReference> iterator)
+            public IteratorAnonymousInnerClassHelper(WeakIdentityMap<K,V> outerInstance)
             {
-                this.OuterInstance = outerInstance;
-                this.Iterator = iterator;
-                next = null;
-                nextIsSet = false;
+                this.outerInstance = outerInstance;
             }
 
-              // holds strong reference to next element in backing iterator:
-            private object next;
-            // the backing iterator was already consumed:
-            private bool nextIsSet;
-            /
-            public virtual bool HasNext()
+            // 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 K Current
             {
-              return nextIsSet || SetNext();
+                get
+                {
+                    return (K)next;
+                }
             }
 
-            public virtual K Next()
+            object IEnumerator.Current
             {
-              if (!HasNext())
-              {
-                throw new Exception();
-              }
-              Debug.Assert(nextIsSet);
-              try
-              {
-                return (K) next;
-              }
-              finally
-              {
-                 // release strong reference and invalidate current value:
-                nextIsSet = false;
-                next = null;
-              }
+                get
+                {
+                    return Current;
+                }
             }
 
-            public virtual void Remove()
+            public void Dispose()
             {
-              throw new System.NotSupportedException();
+                // Nothing to do
             }
 
-            private bool SetNext()
+            
+            public bool MoveNext()
             {
-              Debug.Assert(!nextIsSet);
-              while (Iterator.MoveNext())
-              {
-                next = Iterator.Current;
-                if (next == null)
-                {
-                  // the key was already GCed, we can remove it from backing map:
-                  Iterator.remove();
-                }
-                else
+                while (true)
                 {
-                  // unfold "null" special value:
-                  if (next == NULL)
-                  {
-                    next = null;
-                  }
-                  return nextIsSet = true;
+                    IdentityWeakReference key;
+
+                    // If the next position doesn't exist, exit
+                    if (++position >= outerInstance.BackingStore.Count)
+                    {
+                        position--;
+                        return false;
+                    }
+                    try
+                    {
+                        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;
+                    }
+                    return true;
                 }
-              }
-              return false;
             }
-        }*/
+
+            public void Reset()
+            {
+                throw new NotSupportedException();
+            }
+        }
 
         /// <summary>
         /// Returns an iterator over all values of this map.

http://git-wip-us.apache.org/repos/asf/lucenenet/blob/e8b44e75/src/Lucene.Net.Tests/core/Util/TestWeakIdentityMap.cs
----------------------------------------------------------------------
diff --git a/src/Lucene.Net.Tests/core/Util/TestWeakIdentityMap.cs b/src/Lucene.Net.Tests/core/Util/TestWeakIdentityMap.cs
index 82c5c4c..3eff002 100644
--- a/src/Lucene.Net.Tests/core/Util/TestWeakIdentityMap.cs
+++ b/src/Lucene.Net.Tests/core/Util/TestWeakIdentityMap.cs
@@ -2,7 +2,9 @@ using Lucene.Net.Randomized.Generators;
 using Lucene.Net.Support;
 using NUnit.Framework;
 using System;
+using System.Collections.Concurrent;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Threading;
 
 namespace Lucene.Net.Util
@@ -103,12 +105,12 @@ namespace Lucene.Net.Util
             Assert.AreEqual(3, map.Size());
 
             int c = 0, keysAssigned = 0;
-            for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();
)
+            for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();)
             {
                 //Assert.IsTrue(iter.hasNext()); // try again, should return same result!
                 string k = iter.Current;
-                Assert.IsTrue(k == key1 || k == key2 | k == key3);
                 // 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);
                 c++;
             }
@@ -116,7 +118,7 @@ namespace Lucene.Net.Util
             Assert.AreEqual(1 + 2 + 4, keysAssigned, "all keys must have been seen");
 
             c = 0;
-            for (IEnumerator<string> iter = map.Values.GetEnumerator(); iter.MoveNext();
)
+            for (IEnumerator<string> iter = map.Values.GetEnumerator(); iter.MoveNext();)
             {
                 string v = iter.Current;
                 Assert.IsTrue(v.StartsWith("bar"));
@@ -133,15 +135,13 @@ namespace Lucene.Net.Util
             {
                 try
                 {
-                    //System.RunFinalization();
-                    //System.gc();
                     GC.Collect();
                     int newSize = map.Size();
                     Assert.IsTrue(size >= newSize, "previousSize(" + size + ")>=newSize("
+ newSize + ")");
                     size = newSize;
-                    Thread.Sleep(new TimeSpan(0, 0, 1));
+                    Thread.Sleep(TimeSpan.FromSeconds(1));
                     c = 0;
-                    for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();
)
+                    for (IEnumerator<string> iter = map.Keys.GetEnumerator(); iter.MoveNext();)
                     {
                         Assert.IsNotNull(iter.Current);
                         c++;
@@ -188,22 +188,20 @@ namespace Lucene.Net.Util
             Assert.IsTrue(map.Empty);
         }
 
-        /* LUCENENET TODO: Compile issues
         [Test]
         public virtual void TestConcurrentHashMap()
         {
             // don't make threadCount and keyCount random, otherwise easily OOMs or fails
otherwise:
             const int threadCount = 8, keyCount = 1024;
 
-            System.Threading.ThreadPool.QueueUserWorkItem(;
-            //ExecutorService exec = Executors.newFixedThreadPool(threadCount, new NamedThreadFactory("testConcurrentHashMap"));
+            RunnableAnonymousInnerClassHelper[] workers = new RunnableAnonymousInnerClassHelper[threadCount];
             WeakIdentityMap<object, int?> map = WeakIdentityMap<object, int?>.NewConcurrentHashMap(Random().NextBoolean());
             // we keep strong references to the keys,
             // so WeakIdentityMap will not forget about them:
             AtomicReferenceArray<object> keys = new AtomicReferenceArray<object>(keyCount);
             for (int j = 0; j < keyCount; j++)
             {
-                keys.Set(j, new object());
+                keys[j] = new object();
             }
 
             try
@@ -211,19 +209,33 @@ namespace Lucene.Net.Util
                 for (int t = 0; t < threadCount; t++)
                 {
                     Random rnd = new Random(Random().Next());
-                    exec.execute(new RunnableAnonymousInnerClassHelper(this, keyCount, map,
keys, rnd));
+                    var worker = new RunnableAnonymousInnerClassHelper(this, keyCount, map,
keys, rnd);
+                    workers[t] = worker;
+                    worker.Start();
                 }
             }
             finally
             {
-                exec.shutdown();
-                while (!exec.awaitTermination(1000L, TimeUnit.MILLISECONDS)) ;
+                foreach (var w in workers)
+                {
+                    w.Join(1000L);
+                }
             }
 
+            // LUCENENET: Since assertions were done on the other threads, we need to check
the
+            // results here.
+            for (int i = 0; i < workers.Length; i++)
+            {
+                assertTrue(string.Format(CultureInfo.InvariantCulture,
+                    "worker thread {0} of {1} failed \n" + workers[i].Error, i, workers.Length),
+                    workers[i].Error == null);
+            }
+
+
             // clear strong refs
             for (int j = 0; j < keyCount; j++)
             {
-                keys.Set(j, null);
+                keys[j] = null;
             }
 
             // check that GC does not cause problems in reap() method:
@@ -232,8 +244,6 @@ namespace Lucene.Net.Util
             {
                 try
                 {
-                    //System.runFinalization();
-                    //System.gc();
                     GC.Collect();
                     int newSize = map.Size();
                     Assert.IsTrue(size >= newSize, "previousSize(" + size + ")>=newSize("
+ newSize + ")");
@@ -256,63 +266,77 @@ namespace Lucene.Net.Util
             }
         }
 
-        private class RunnableAnonymousInnerClassHelper : IThreadRunnable
+        private class RunnableAnonymousInnerClassHelper : ThreadClass
         {
-            private readonly TestWeakIdentityMap OuterInstance;
+            private readonly TestWeakIdentityMap outerInstance;
 
-            private int KeyCount;
-            private WeakIdentityMap<object, int?> Map;
-            private AtomicReferenceArray<object> Keys;
-            private Random Rnd;
+            private readonly int keyCount;
+            private readonly WeakIdentityMap<object, int?> map;
+            private AtomicReferenceArray<object> keys;
+            private readonly Random rnd;
+            private volatile Exception error;
 
             public RunnableAnonymousInnerClassHelper(TestWeakIdentityMap outerInstance, int
keyCount, WeakIdentityMap<object, int?> map, AtomicReferenceArray<object> keys,
Random rnd)
             {
-                this.OuterInstance = outerInstance;
-                this.KeyCount = keyCount;
-                this.Map = map;
-                this.Keys = keys;
-                this.Rnd = rnd;
+                this.outerInstance = outerInstance;
+                this.keyCount = keyCount;
+                this.map = map;
+                this.keys = keys;
+                this.rnd = rnd;
             }
 
-            public void Run()
+            public Exception Error
             {
-                int count = AtLeast(Rnd, 10000);
-                for (int i = 0; i < count; i++)
+                get { return error; }
+            }
+
+
+            public override void Run()
+            {
+                int count = AtLeast(rnd, 10000);
+                try
                 {
-                    int j = Rnd.Next(KeyCount);
-                    switch (Rnd.Next(5))
+                    for (int i = 0; i < count; i++)
                     {
-                        case 0:
-                            Map.Put(Keys.Get(j), Convert.ToInt32(j));
-                            break;
-                        case 1:
-                            int? v = Map.Get(Keys.Get(j));
-                            if (v != null)
-                            {
-                                Assert.AreEqual(j, (int)v);
-                            }
-                            break;
-                        case 2:
-                            Map.Remove(Keys.Get(j));
-                            break;
-                        case 3:
-                            // renew key, the old one will be GCed at some time:
-                            Keys.Set(j, new object());
-                            break;
-                        case 4:
-                            // check iterator still working
-                            for (IEnumerator<object> it = Map.Keys.GetEnumerator();
it.MoveNext();)
-                            {
-                                Assert.IsNotNull(it.Current);
-                            }
-                            break;
-                        default:
-                            Assert.Fail("Should not get here.");
-                            break;
+                        int j = rnd.Next(keyCount);
+                        switch (rnd.Next(5))
+                        {
+                            case 0:
+                                map.Put(keys[j], Convert.ToInt32(j));
+                                break;
+                            case 1:
+                                int? v = map.Get(keys[j]);
+                                if (v != null)
+                                {
+                                    Assert.AreEqual(j, (int)v);
+                                }
+                                break;
+                            case 2:
+                                map.Remove(keys[j]);
+                                break;
+                            case 3:
+                                // renew key, the old one will be GCed at some time:
+                                keys[j] = new object();
+                                break;
+                            case 4:
+                                // check iterator still working
+                                for (IEnumerator<object> it = map.Keys.GetEnumerator();
it.MoveNext();)
+                                {
+                                    Assert.IsNotNull(it.Current);
+                                }
+                                break;
+                            default:
+                                Assert.Fail("Should not get here.");
+                                break;
+                        }
                     }
                 }
+                catch (Exception e)
+                {
+                    e.printStackTrace();
+                    this.error = e;
+                }
             }
         }
-        */
     }
 }
\ No newline at end of file


Mime
View raw message