Forráskód Böngészése

[System.Core] Fix issue in Join where some data might have been dismissed by accident

Jérémie Laval 13 éve
szülő
commit
4ceeaaae89

+ 30 - 5
mcs/class/System.Core/System.Linq.Parallel.QueryNodes/QueryJoinNode.cs

@@ -121,9 +121,10 @@ namespace System.Linq.Parallel.QueryNodes
 			IEnumerator<V> eSecond = second.GetEnumerator ();
 
 			try {
-				while (eFirst.MoveNext ()) {
-					if (!eSecond.MoveNext ())
-						yield break;
+				bool fstHasCurrent = false, sndHasCurrent = false;
+				Tuple<VSlot<U>, VSlot<V>> kvp;
+
+				while ((fstHasCurrent = eFirst.MoveNext ()) & (sndHasCurrent = eSecond.MoveNext ())) {
 
 					U e1 = eFirst.Current;
 					V e2 = eSecond.Current;
@@ -136,8 +137,6 @@ namespace System.Linq.Parallel.QueryNodes
 						continue;
 					}
 					
-					Tuple<VSlot<U>, VSlot<V>> kvp;
-					
 					do {
 						if (store.TryRemove (key1, out kvp) && kvp.Item2.HasValue) {
 							yield return resultor (e1, kvp.Item2.Value);
@@ -152,6 +151,32 @@ namespace System.Linq.Parallel.QueryNodes
 						}
 					} while (!store.TryAdd (key2, Tuple.Create (new VSlot<U> (), new VSlot<V> (e2))));
 				}
+				if (fstHasCurrent) {
+					do {
+						U e1 = eFirst.Current;
+						TKey key1 = fKeySelect (e1);
+
+						do {
+							if (store.TryRemove (key1, out kvp) && kvp.Item2.HasValue) {
+								yield return resultor (e1, kvp.Item2.Value);
+								break;
+							}
+						} while (!store.TryAdd (key1, Tuple.Create (new VSlot<U> (e1), new VSlot<V> ())));
+					} while (eFirst.MoveNext ());
+				}
+				if (sndHasCurrent) {
+					do {
+						V e2 = eSecond.Current;
+						TKey key2 = sKeySelect (e2);
+
+						do {
+							if (store.TryRemove (key2, out kvp) && kvp.Item1.HasValue) {
+								yield return resultor (kvp.Item1.Value, e2);
+								break;
+							}
+						} while (!store.TryAdd (key2, Tuple.Create (new VSlot<U> (), new VSlot<V> (e2))));
+					} while (eSecond.MoveNext ());
+				}
 			} finally {
 				eFirst.Dispose ();
 				eSecond.Dispose ();

+ 9 - 0
mcs/class/System.Core/Test/System.Linq/ParallelEnumerableTests.cs

@@ -611,6 +611,15 @@ namespace MonoTests.System.Linq
 			});
 		}
 
+		[Test]
+		public void SmallJoinTest ()
+		{
+			var items = new [] { 1, 2, 3 };
+			var items2 = new [] { 1, 2, 3, 4 };
+			var actual = items.AsReallyParallel ().Join (items2.AsReallyParallel (), i => i, i => i, (e1, e2) => e1 + e2);
+			AreEquivalent (new[] { 2, 4, 6 }, actual, 1);
+		}
+
 		[Test]
 		[Category ("NotWorking")] // Deadlocks randomly
 		public void TestGroupBy ()