Merge pull request #498 from Unroll-Me/master
[mono.git] / mcs / class / System.Core / System.Linq.Parallel.QueryNodes / QueryJoinNode.cs
index ba6f8a39a0566c01ec3111a06e51ad2c1fa0bdb3..61b9162e1f32d4b122f5b0b42c488bcf7dcf3789 100644 (file)
@@ -24,7 +24,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-#if NET_4_0
+#if NET_4_0 || MOBILE
 using System;
 using System.Threading;
 using System.Collections;
@@ -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 ();