2010-04-15 Jérémie Laval <jeremie.laval@gmail.com>
authorJérémie Laval <jeremie.laval@gmail.com>
Thu, 15 Apr 2010 19:01:50 +0000 (19:01 -0000)
committerJérémie Laval <jeremie.laval@gmail.com>
Thu, 15 Apr 2010 19:01:50 +0000 (19:01 -0000)
In class/System.Core/:
   * net_4_0_System.Core.dll.sources: add PLinq sources

In class/System.Core/System.Linq/:
   * OrderedParallelQuery.cs:
   * ParallelEnumerable.cs:
   * ParallelExecuter.cs:
   * ParallelPartitioner.cs:
   * ParallelQuery.cs:
   * ParallelQueryEnumerator.cs: First check-in of PLinq

In class/System.Core/System.Linq/Internal/:
   * AggregationList.cs:
   * ConcurrentGrouping.cs:
   * ConcurrentLookup.cs:
   * OrderingEnumerator.cs:
   * ParallelQuickSort.cs:
   * RangeList.cs:
   * RepeatList.cs:
   * ReverseList.cs:
   * StripPartitioner.cs: Initial check-in of PLinq

In class/System.Core/System.Linq/Internal/QueryNodes/:
   * QueryBaseNode.cs:
   * QueryCastNode.cs:
   * QueryChildNode.cs:
   * QueryConcatNode.cs:
   * QueryDefaultEmptyNode.cs:
   * QueryGroupByNode.cs:
   * QueryMuxNode.cs:
   * QueryOptionNode.cs:
   * QueryOrderByNode.cs:
   * QueryOrderGuardNode.cs:
   * QueryOrderedStreamNode.cs:
   * QueryReverseNode.cs:
   * QuerySelectManyNode.cs:
   * QuerySelectNode.cs:
   * QuerySetNode.cs:
   * QueryStartNode.cs:
   * QueryStreamNode.cs:
   * QueryWhereNode.cs:
   * QueryZipNode.cs:
   * WrapHelper.cs: Initial check-in of PLinq

In class/System.Core/System.Linq/Internal/Visitors/:
   * INodeVisitor.cs:
   * IVisitableNode.cs:
   * QueryCheckerVisitor.cs:
   * QueryOptions.cs: First check-in of PLinq

svn path=/trunk/mcs/; revision=155533

45 files changed:
mcs/class/System.Core/ChangeLog
mcs/class/System.Core/System.Linq/ChangeLog
mcs/class/System.Core/System.Linq/Internal/AggregationList.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/ChangeLog [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/ConcurrentGrouping.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/ConcurrentLookup.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/OrderingEnumerator.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/ParallelQuickSort.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/ChangeLog
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryBaseNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryCastNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryChildNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryConcatNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryDefaultEmptyNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryGroupByNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryMuxNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOptionNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderByNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderGuardNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderedStreamNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryReverseNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectManyNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySetNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStartNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStreamNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryWhereNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryZipNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/QueryNodes/WrapHelper.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/RangeList.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/RepeatList.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/ReverseList.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/StripPartitioner.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/Visitors/ChangeLog [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/Visitors/INodeVisitor.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/Visitors/IVisitableNode.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/Visitors/QueryCheckerVisitor.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/Internal/Visitors/QueryOptions.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/OrderedParallelQuery.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/ParallelEnumerable.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/ParallelExecuter.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/ParallelPartitioner.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/ParallelQuery.cs [new file with mode: 0644]
mcs/class/System.Core/System.Linq/ParallelQueryEnumerator.cs [new file with mode: 0644]
mcs/class/System.Core/net_4_0_System.Core.dll.sources

index 3be9c964872edcbf51f271565323b01e6d073a94..2fdd6567ec657f618432d1346c1ef76265f10bc0 100644 (file)
@@ -1,3 +1,7 @@
+2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
+
+       * net_4_0_System.Core.dll.sources: add PLinq sources
+
 2010-04-06  Jb Evain  <jbevain@novell.com>
 
        * net_4_0_System.Core.dll.sources: add files to support ToQueryable.
index 4a50346bbaf754d890c4d0b9da730ef400dbdde7..09221b2afb31b1bfc8c03f96410d19ec1218965a 100644 (file)
@@ -1,3 +1,12 @@
+2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
+
+       * OrderedParallelQuery.cs:
+       * ParallelEnumerable.cs:
+       * ParallelExecuter.cs:
+       * ParallelPartitioner.cs:
+       * ParallelQuery.cs:
+       * ParallelQueryEnumerator.cs: First check-in of PLinq
+
 2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
 
        * ParallelExecutionMode.cs:
diff --git a/mcs/class/System.Core/System.Linq/Internal/AggregationList.cs b/mcs/class/System.Core/System.Linq/Internal/AggregationList.cs
new file mode 100644 (file)
index 0000000..50bee2b
--- /dev/null
@@ -0,0 +1,135 @@
+#if NET_4_0
+//
+// AggregationList.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class AggregationList<T> : IList<T>
+       {
+               readonly IList<IList<T>> listes;
+               readonly int count;
+
+               internal AggregationList (IList<IList<T>> listes)
+               {
+                       this.listes = listes;
+                       foreach (var l in listes)
+                               count += l.Count;
+               }
+
+               public int IndexOf (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Insert (int index, T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public T this[int index] {
+                       get {
+                               int listIndex, newIndex;
+                               GetModifiedIndexes (index, out listIndex, out newIndex);
+
+                               return listes[listIndex][newIndex];
+                       }
+                       set {
+                               throw new NotImplementedException();
+                       }
+               }
+
+               void GetModifiedIndexes (int index, out int listIndex, out int newIndex)
+               {
+                       listIndex = 0;
+                       newIndex = index;
+
+                       while (newIndex >= listes[listIndex].Count) {
+                               newIndex -= listes[listIndex].Count;
+                               listIndex++;
+
+                               if (listIndex > listes.Count)
+                                       throw new ArgumentOutOfRangeException ();
+                       }
+               }
+
+               public void Add (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Contains (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void CopyTo (T[] array, int arrayIndex)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Remove (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+               {
+                       return null;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return null;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/ChangeLog b/mcs/class/System.Core/System.Linq/Internal/ChangeLog
new file mode 100644 (file)
index 0000000..e7aa198
--- /dev/null
@@ -0,0 +1,12 @@
+2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
+
+       * AggregationList.cs:
+       * ConcurrentGrouping.cs:
+       * ConcurrentLookup.cs:
+       * OrderingEnumerator.cs:
+       * ParallelQuickSort.cs:
+       * RangeList.cs:
+       * RepeatList.cs:
+       * ReverseList.cs:
+       * StripPartitioner.cs: Initial check-in of PLinq
+
diff --git a/mcs/class/System.Core/System.Linq/Internal/ConcurrentGrouping.cs b/mcs/class/System.Core/System.Linq/Internal/ConcurrentGrouping.cs
new file mode 100644 (file)
index 0000000..f1cdd3c
--- /dev/null
@@ -0,0 +1,65 @@
+#if NET_4_0
+//
+// ConcurrentGrouping.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class ConcurrentGrouping<TKey, TElement> : IGrouping<TKey, TElement>
+       {
+               TKey key;
+               IEnumerable<TElement> elements;
+
+               internal ConcurrentGrouping (TKey key, IEnumerable<TElement> elements)
+               {
+                       this.key = key;
+                       this.elements = elements;
+               }
+
+               public TKey Key {
+                       get {
+                               return key;
+                       }
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return ((IEnumerable)elements).GetEnumerator ();
+               }
+
+               IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator ()
+               {
+                       return elements.GetEnumerator ();
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/ConcurrentLookup.cs b/mcs/class/System.Core/System.Linq/Internal/ConcurrentLookup.cs
new file mode 100644 (file)
index 0000000..a39ccb2
--- /dev/null
@@ -0,0 +1,117 @@
+#if NET_4_0
+//
+// ConcurrentLookup.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class ConcurrentLookup<TKey, TElement> : ILookup<TKey, TElement>
+       {
+               ConcurrentDictionary<TKey, IEnumerable<TElement>> dictionary;
+
+               private class AddSlot
+               {
+                       TElement element;
+
+                       internal AddSlot (TElement element)
+                       {
+                               this.element = element;
+                       }
+
+                       internal IEnumerable<TElement> AddMethod (TKey key)
+                       {
+                               List<TElement> list = new List<TElement> ();
+                               list.Add (element);
+
+                               return list;
+                       }
+
+                       internal IEnumerable<TElement> UpdateMethod (TKey key, IEnumerable<TElement> old)
+                       {
+                               ICollection<TElement> coll = (ICollection<TElement>)old;
+                               coll.Add (element);
+
+                               return coll;
+                       }
+               }
+
+               internal ConcurrentLookup (IEqualityComparer<TKey> comparer)
+               {
+                       this.dictionary = new ConcurrentDictionary<TKey, IEnumerable<TElement>> (comparer);
+               }
+
+               internal void Add (TKey key, TElement element)
+               {
+                       AddSlot slot = new AddSlot (element);
+                       dictionary.AddOrUpdate (key, slot.AddMethod, slot.UpdateMethod);
+               }
+
+               public bool Contains (TKey key)
+               {
+                       return dictionary.ContainsKey (key);
+               }
+
+               public IEnumerable<TElement> this[TKey key] {
+                       get {
+                               return dictionary[key];
+                       }
+               }
+
+               public int Count {
+                       get {
+                               return dictionary.Count;
+                       }
+               }
+               
+               public IList<TKey> Keys {
+                       get {
+                               return (IList<TKey>)dictionary.Keys;
+                       }
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return (IEnumerator)GetEnumeratorInternal ();
+               }
+
+               IEnumerator<IGrouping<TKey, TElement>> IEnumerable<IGrouping<TKey, TElement>>.GetEnumerator ()
+               {
+                       return GetEnumeratorInternal ();
+               }
+
+               IEnumerator<IGrouping<TKey, TElement>> GetEnumeratorInternal ()
+               {
+                       return dictionary.Select ((pair) => new ConcurrentGrouping<TKey, TElement> (pair.Key, pair.Value)).GetEnumerator ();
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/OrderingEnumerator.cs b/mcs/class/System.Core/System.Linq/Internal/OrderingEnumerator.cs
new file mode 100644 (file)
index 0000000..61f0949
--- /dev/null
@@ -0,0 +1,144 @@
+#if NET_4_0
+//
+// OrderingEnumerator.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       // Remove use of KeyedBuffer
+       /* Instead, we use a fixed array of nullables. The Add method put the object in its right slot based on the index.
+        * We use a barrier for synchronisation, each add check that the current range of index accepted in the array is correct
+        * and if not wait on the Barrier. The Barrier's generation index is used to calculate the next range.
+        * The IEnumerator interface simply skim the array in order and return the objects.
+        */
+       internal class OrderingEnumerator<T> : IEnumerator<T>
+       {
+               readonly int num;
+
+               public BlockingCollection<KeyValuePair<long, T>> KeyedBuffer;
+               KeyValuePair<long, T>?[] store;
+
+               IEnumerator<KeyValuePair<long, T>?> currEnum;
+               KeyValuePair<long, T> curr;
+
+               internal OrderingEnumerator (int num)
+               {
+                       this.num = num;
+                       KeyedBuffer = new BlockingCollection<KeyValuePair<long, T>> ();
+                       store = new KeyValuePair<long, T>?[num];
+               }
+
+               public void Dispose ()
+               {
+
+               }
+
+               public void Reset ()
+               {
+
+               }
+
+               public bool MoveNext ()
+               {
+                       if (currEnum == null || !currEnum.MoveNext () || !currEnum.Current.HasValue) {
+                               if (!UpdateCurrent ())
+                                       return false;
+                       }
+
+                       if (!currEnum.Current.HasValue)
+                               return false;
+
+                       curr = currEnum.Current.Value;
+
+                       return true;
+               }
+
+               public T Current {
+                       get {
+                               return curr.Value;
+                       }
+               }
+
+               object IEnumerator.Current {
+                       get {
+                               return curr.Value;
+                       }
+               }
+
+               bool UpdateCurrent ()
+               {
+                       if (KeyedBuffer.IsCompleted)
+                               return false;
+
+                       if (KeyedBuffer.Count != num) {
+                               SpinWait sw = new SpinWait ();
+                               while (KeyedBuffer.Count < num && !KeyedBuffer.IsAddingCompleted) {
+                                       sw.SpinOnce ();
+                               }
+                       }
+
+                       // We gather the lot without removing it
+                       int i = 0;
+                       foreach (KeyValuePair<long, T> item in KeyedBuffer.GetConsumingEnumerable ()) {
+                               store[i] = item;
+
+                               if (++i == num || KeyedBuffer.IsCompleted)
+                                       break;
+                       }
+
+                       for (int k = i; k < num; k++) {
+                               store[k] = null;
+                       }
+
+                       Array.Sort (store, ArraySort);
+
+                       currEnum = ((IEnumerable<KeyValuePair<long, T>?>)store).GetEnumerator ();
+
+                       return currEnum.MoveNext ();
+               }
+
+               int ArraySort (KeyValuePair<long, T>? e1, KeyValuePair<long, T>? e2)
+               {
+                       if (!e1.HasValue) {
+                               if (!e2.HasValue)
+                                       return 0;
+
+                               if (e2.HasValue)
+                                       return 1;
+                       }
+                       if (!e2.HasValue && e1.HasValue)
+                               return -1;
+
+                       return e1.Value.Key.CompareTo (e2.Value.Key);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/ParallelQuickSort.cs b/mcs/class/System.Core/System.Linq/Internal/ParallelQuickSort.cs
new file mode 100644 (file)
index 0000000..52d841b
--- /dev/null
@@ -0,0 +1,285 @@
+#if NET_4_0
+//
+// ParallelQuickSort.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       // HACK: ATM: parallelization of the sort is disabled as task
+       // add more overhead than gain
+       internal class ParallelQuickSort<T>
+       {
+               readonly Comparison<T> comparison;
+               readonly IList<T> list;
+               readonly int[] indexes;
+
+               class SortedCollection : IList<T>
+               {
+                       int[] indexes;
+                       IList<T> source;
+
+                       public SortedCollection (IList<T> source, int[] indexes)
+                       {
+                               this.indexes = indexes;
+                               this.source = source;
+                       }
+
+                       public int IndexOf (T item)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public void Insert (int index, T item)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public void RemoveAt (int index)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public T this[int index] {
+                               get {
+                                       return source[indexes[index]];
+                               }
+                               set {
+                                       throw new NotImplementedException();
+                               }
+                       }
+
+                       public void Add (T item)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public void Clear ()
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public bool Contains (T item)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public void CopyTo (T[] array, int arrayIndex)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public bool Remove (T item)
+                       {
+                               throw new NotImplementedException();
+                       }
+
+                       public int Count {
+                               get {
+                                       return source.Count;
+                               }
+                       }
+
+                       public bool IsReadOnly {
+                               get {
+                                       return true;
+                               }
+                       }
+
+                       IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+                       {
+                               return null;
+                       }
+
+                       IEnumerator IEnumerable.GetEnumerator ()
+                       {
+                               return null;
+                       }
+               }
+
+               private ParallelQuickSort (IList<T> list, Comparison<T> comparison)
+               {
+                       this.comparison = comparison;
+                       this.list = list;
+                       this.indexes = CreateIndexes (list.Count);
+               }
+
+               static int[] CreateIndexes (int length)
+               {
+                       var indexes = new int[length];
+                       for (int i = 0; i < length; i++)
+                               indexes [i] = i;
+
+                       return indexes;
+               }
+
+               SortedCollection DoSort ()
+               {
+                       if (list.Count > 1) {
+                               if (list.Count < 5)
+                                       InsertionSort (0, list.Count - 1);
+                               else
+                                       Sort (0, list.Count - 1);
+                       }
+
+                       return new SortedCollection (list, indexes);
+               }
+
+               int Comparison (int index1, int index2)
+               {
+                       return comparison (list[index1], list[index2]);
+               }
+
+               void Sort (int left, int right)
+               {
+                       if (left + 3 <= right) {
+                               int l = left, r = right - 1, pivot = MedianOfThree (left, right);
+                               while (true) {
+                                       while (Comparison (indexes [++l], pivot) < 0) { }
+                                       while (Comparison (indexes [--r], pivot) > 0) { }
+                                       if (l < r)
+                                               Swap (l, r);
+                                       else
+                                               break;
+                               }
+
+                               // Restore pivot
+                               Swap (l, right - 1);
+                               // Partition and sort
+                               Sort (left, l - 1);
+                               Sort (l + 1, right);
+                       } else
+                               // If there are three items in the subarray, insertion sort is better
+                               InsertionSort (left, right);
+               }
+
+               /*void Sort (int left, int right, int depth)
+               {
+                       int l = left, r = right - 1, pivot = MedianOfThree (left, right);
+                       while (true) {
+                               while (Comparison (indexes[++l], pivot) < 0);
+                               while (Comparison (indexes[--r], pivot) > 0);
+                               if (l < r)
+                                       Swap (l, r);
+                               else
+                                       break;
+                       }
+
+                       // Restore pivot
+                       Swap (l, right - 1);
+
+                       // Partition and sort in parallel if appropriate
+                       /*if (depth < maxDepth) {
+                               depth <<= 1;
+                               Task t = Task.Factory.StartNew (() => Sort (left, l - 1, depth));
+                               Sort (l + 1, right, depth);
+
+                               t.Wait ();
+                       } else {*/
+                               // Sequential
+               /*              Sort (left, l - 1);
+                               Sort (l + 1, right);
+                       //}
+               }*/
+
+               /*void ShellSort (int left, int right)
+               {
+                       int[] gaps = new int[] { 4, 1};
+
+                       for (int ic = 0; ic < gaps.Length; ic++) {
+                               int inc = gaps[ic];
+                               int l = left + inc;
+                               for (int i = l; i <= right; i++) {
+                                       T temp = list[i];
+                                       int j = i;
+                                       for (; j >= l && comparison (list[j - inc], temp) > 1; j -= inc)
+                                               list[j] = list[j - inc];
+                                       list[j] = temp;
+                               }
+                       }
+               }*/
+
+               void InsertionSort (int left, int right)
+               {
+                       for (int i = left + 1; i <= right; i++) {
+                               int j, tmp = indexes [i];
+
+                               for (j = i; j > left && Comparison (tmp, indexes [j - 1]) < 0; j--)
+                                       indexes [j] = indexes [j - 1];
+
+                               indexes [j] = tmp;
+                       }
+               }
+
+               /*
+               void InsertionSort (int left, int right)
+               {
+                       for (int i = left + 1; i <= right; i++) {
+                               int j;
+                               T tmp = list[i];
+
+                               for (j = i; j > left && comparison (tmp, list [j - 1]) < 0; j--)
+                                       list [j] = list [j - 1];
+
+                               list [j] = tmp;
+                       }
+               }*/
+
+               void Swap (int left, int right)
+               {
+                       int temp = indexes [right];
+                       indexes [right] = indexes [left];
+                       indexes [left] = temp;
+               }
+
+               int MedianOfThree (int left, int right)
+               {
+                       int center = (left + right) >> 1;
+                       if (Comparison (indexes[center], indexes[left]) < 0)
+                               Swap (left, center);
+                       if (Comparison (indexes[right], indexes[left]) < 0)
+                               Swap (left, right);
+                       if (Comparison (indexes[right], indexes[center]) < 0)
+                               Swap (center, right);
+                       Swap (center, right - 1);
+
+                       return indexes[right - 1];
+               }
+
+               public static IList<T> Sort (IList<T> list, Comparison<T> comparison)
+               {
+                       ParallelQuickSort<T> qs = new ParallelQuickSort<T> (list, comparison);
+
+                       return qs.DoSort ();
+               }
+       }
+}
+#endif
index f96bf68baa7867eb2eca5e0ac129b8ccb8ddf069..e9e87fa266d8c32c294566939dc2590f40930b2a 100644 (file)
@@ -1,3 +1,26 @@
+2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
+
+       * QueryBaseNode.cs:
+       * QueryCastNode.cs:
+       * QueryChildNode.cs:
+       * QueryConcatNode.cs:
+       * QueryDefaultEmptyNode.cs:
+       * QueryGroupByNode.cs:
+       * QueryMuxNode.cs:
+       * QueryOptionNode.cs:
+       * QueryOrderByNode.cs:
+       * QueryOrderGuardNode.cs:
+       * QueryOrderedStreamNode.cs:
+       * QueryReverseNode.cs:
+       * QuerySelectManyNode.cs:
+       * QuerySelectNode.cs:
+       * QuerySetNode.cs:
+       * QueryStartNode.cs:
+       * QueryStreamNode.cs:
+       * QueryWhereNode.cs:
+       * QueryZipNode.cs:
+       * WrapHelper.cs: Initial check-in of PLinq
+
 2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
 
        * SetInclusion.cs: Initial check-in of PLinq (enum)
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryBaseNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryBaseNode.cs
new file mode 100644 (file)
index 0000000..14c1455
--- /dev/null
@@ -0,0 +1,49 @@
+#if NET_4_0
+//
+// QueryBaseNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal abstract class QueryBaseNode<T> : IVisitableNode
+       {
+               public virtual void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T> (this);
+               }
+
+               internal abstract IList<IEnumerable<T>> GetEnumerables (QueryOptions options);
+
+               internal abstract IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options);
+
+               internal abstract IEnumerable<T> GetSequential ();
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryCastNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryCastNode.cs
new file mode 100644 (file)
index 0000000..1bb6f29
--- /dev/null
@@ -0,0 +1,72 @@
+#if NET_4_0
+//
+// QueryCastNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class QueryCastNode<T> : QueryStreamNode<object, T>
+       {
+               public QueryCastNode (QueryBaseNode<T> source)
+                       : base (source, false)
+               {
+
+               }
+               
+               internal override IEnumerable<object> GetSequential ()
+               {
+                       return Parent.GetSequential ().Cast<object> ();
+               }
+               
+               internal override IList<IEnumerable<KeyValuePair<long, object>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, T>>> src = Parent.GetOrderedEnumerables (options);
+                       IEnumerable<KeyValuePair<long, object>>[] result = new IEnumerable<KeyValuePair<long, object>> [src.Count];
+                       
+                       for (int i = 0; i < src.Count; i++)
+                               result[i] = src[i].Select ((e) => new KeyValuePair<long, object> (e.Key, (object)e.Value));
+                       
+                       return result;
+               }
+               
+               internal override IList<IEnumerable<object>> GetEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<T>> src = Parent.GetEnumerables (options);
+                       IEnumerable<object>[] result = new IEnumerable<object> [src.Count];
+                       
+                       for (int i = 0; i < src.Count; i++)
+                               result[i] = src[i].Cast<object> ();
+                       
+                       return result;
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryChildNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryChildNode.cs
new file mode 100644 (file)
index 0000000..c58834a
--- /dev/null
@@ -0,0 +1,54 @@
+#if NET_4_0
+//
+// QueryChildNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace System.Linq
+{
+       internal abstract class QueryChildNode<T, TParent> : QueryBaseNode<T>
+       {
+               QueryBaseNode<TParent> parent;
+
+               internal QueryChildNode (QueryBaseNode<TParent> parent)
+               //      : base (isOrdered, true)
+               {
+                       this.parent = parent;
+               }
+
+               internal QueryBaseNode<TParent> Parent {
+                       get {
+                               return parent;
+                       }
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T, TParent> (this);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryConcatNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryConcatNode.cs
new file mode 100644 (file)
index 0000000..16a0e77
--- /dev/null
@@ -0,0 +1,86 @@
+#if NET_4_0
+//
+// QueryConcatNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class QueryConcatNode<TSource> : QueryMuxNode<TSource, TSource, TSource>
+       {
+               public QueryConcatNode (QueryBaseNode<TSource> first, QueryBaseNode<TSource> second)
+                       : this (first, second)
+               {
+               }
+
+               internal override IList<IEnumerable<TSource>> GetEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<TSource>> first = Parent.GetEnumerables (options);
+                       IList<IEnumerable<TSource>> second = Second.GetEnumerables (options);
+
+                       IEnumerable<TSource>[] result = new IEnumerable<TSource>[first.Count];
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = CombineEnumerables (first[i], second[i]);
+
+                       return result;
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TSource>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> first = Parent.GetOrderedEnumerables (options);
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> second = Second.GetOrderedEnumerables (options);
+
+                       IEnumerable<KeyValuePair<long, TSource>>[] result = new IEnumerable<KeyValuePair<long, TSource>>[first.Count];
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = CombineEnumerables (first[i], second[i]);
+
+                       return result;
+               }
+
+               internal override IEnumerable<TSource> GetSequential ()
+               {
+                       IEnumerable<TSource> first = Parent.GetSequential ();
+                       IEnumerable<TSource> second = Second.GetSequential ();
+
+                       return first.Concat (second);
+               }
+
+               IEnumerable<TResult> CombineEnumerables<TResult> (IEnumerable<TResult> f, IEnumerable<TResult> s)
+               {
+                       foreach (var e in f)
+                               yield return e;
+                       foreach (var e in s)
+                               yield return e;
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryDefaultEmptyNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryDefaultEmptyNode.cs
new file mode 100644 (file)
index 0000000..e5463d0
--- /dev/null
@@ -0,0 +1,93 @@
+#if NET_4_0
+//
+// QueryDefaultEmptyNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class QueryDefaultEmptyNode<TSource> : QueryStreamNode<TSource, TSource>
+       {
+               TSource defaultValue;
+               
+               internal QueryDefaultEmptyNode (QueryBaseNode<TSource> parent, TSource defaultValue)
+                       : base (parent, false)
+               {
+                       this.defaultValue = defaultValue;
+               }
+               
+               internal override IEnumerable<TSource> GetSequential ()
+               {
+                       return Parent.GetSequential ().DefaultIfEmpty (defaultValue);
+               }
+               
+               internal override IList<IEnumerable<TSource>> GetEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<TSource>> enumerables = Parent.GetEnumerables (options);
+                       CountdownEvent evt = new CountdownEvent (enumerables.Count);
+                       IEnumerable<TSource>[] result = new IEnumerable<TSource>[enumerables.Count];
+                       
+                       for (int i = 0; i < enumerables.Count; i++)
+                               result[i] = GetEnumerableInternal<TSource> (enumerables[i], evt, 
+                                                                           (s) => s);
+                       
+                       return result;
+               }
+               
+               internal override IList<IEnumerable<KeyValuePair<long, TSource>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> enumerables = Parent.GetOrderedEnumerables (options);
+                       CountdownEvent evt = new CountdownEvent (enumerables.Count);
+                       IEnumerable<KeyValuePair<long, TSource>>[] result = new IEnumerable<KeyValuePair<long, TSource>>[enumerables.Count];
+                       
+                       for (int i = 0; i < enumerables.Count; i++)
+                               result[i] = GetEnumerableInternal<KeyValuePair<long, TSource>> (enumerables[i], evt, 
+                                                                                               (s) => new KeyValuePair<long, TSource> (0, s));
+                       
+                       return result;
+               }
+               
+               IEnumerable<TSecond> GetEnumerableInternal<TSecond> (IEnumerable<TSecond> source, 
+                                                                    CountdownEvent evt,
+                                                                    Func<TSource, TSecond> converter)
+               {
+                       bool processed = false;
+                       
+                       foreach (TSecond second in source) {
+                               processed = true;
+                               yield return second;
+                       }
+                       
+                       if (!processed && evt.Signal ())
+                               yield return converter (defaultValue);
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryGroupByNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryGroupByNode.cs
new file mode 100644 (file)
index 0000000..4ccaac9
--- /dev/null
@@ -0,0 +1,76 @@
+#if NET_4_0
+//
+// QueryOrderByNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QueryGroupByNode<TSource, TKey, TElement> : QueryStreamNode<IGrouping<TKey, TElement>, TSource>
+       {
+               Func<TSource, TKey> keySelector;
+               Func<TSource, TElement> elementSelector;
+               IEqualityComparer<TKey> comparer;
+               
+               public QueryGroupByNode (QueryBaseNode<TSource> parent,
+                                        Func<TSource, TKey> keySelector, 
+                                        Func<TSource, TElement> elementSelector,
+                                        IEqualityComparer<TKey> comparer)
+                       : base (parent, false)
+               {
+                       this.keySelector = keySelector;
+                       this.elementSelector = elementSelector;
+                       this.comparer = comparer;
+               }
+               
+               internal override IEnumerable<IGrouping<TKey, TElement>> GetSequential ()
+               {
+                       IEnumerable<TSource> src =  Parent.GetSequential ();
+                       
+                       return src.GroupBy (keySelector, elementSelector, comparer);
+               }
+               
+               internal override IList<IEnumerable<KeyValuePair<long, IGrouping<TKey, TElement>>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       //ConcurrentLookup<TKey, TElement> lookup = new ConcurrentLookup<TKey, TElement> ();
+                       
+                       //ParallelExecuter.ProcessAndBlock (Parent, (e) => lookup.Add (keySelector (e), elementSelector (e)));
+                       
+                       throw new System.NotImplementedException();
+               }
+               
+               internal override IList<IEnumerable<IGrouping<TKey, TElement>>> GetEnumerables (QueryOptions options)
+               {
+                       throw new System.NotImplementedException();
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryMuxNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryMuxNode.cs
new file mode 100644 (file)
index 0000000..49fbab6
--- /dev/null
@@ -0,0 +1,58 @@
+#if NET_4_0
+//
+// QueryMuxNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal abstract class QueryMuxNode<TFirst, TSecond, TResult> : QueryChildNode<TResult, TFirst>
+       {
+               QueryBaseNode<TSecond> second;
+
+               internal QueryMuxNode (QueryBaseNode<TFirst> parent, QueryBaseNode<TSecond> second)
+                       : base (parent)
+               {
+                       this.second = second;
+               }
+
+               internal QueryBaseNode<TSecond> Second {
+                       get {
+                               return second;
+                       }
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit (this);
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOptionNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOptionNode.cs
new file mode 100644 (file)
index 0000000..ac096c1
--- /dev/null
@@ -0,0 +1,155 @@
+#if NET_4_0
+//
+// QueryOptionNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       // The first four elements correspond to the public operator With*
+       // Last CancellationToken parameter is used internally for ImplementerToken
+       using OptionsList = Tuple<ParallelMergeOptions?, ParallelExecutionMode?, CancellationToken?, int, CancellationTokenSource>;
+
+       internal class QueryOptionNode<T> : QueryChildNode<T, T>
+       {
+
+               public QueryOptionNode (QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+
+               }
+
+               internal virtual OptionsList GetOptions ()
+               {
+                       return new OptionsList (null, null, null, -1, null);
+               }
+
+               internal override IList<IEnumerable<T>> GetEnumerables (QueryOptions options)
+               {
+                       return Parent.GetEnumerables (options);
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       return Parent.GetOrderedEnumerables (options);
+               }
+
+               internal override IEnumerable<T> GetSequential ()
+               {
+                       return Parent.GetSequential ();
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T> (this);
+               }
+       }
+
+       internal class ParallelExecutionModeNode<T> : QueryOptionNode<T>
+       {
+               ParallelExecutionMode mode;
+
+               internal ParallelExecutionModeNode (ParallelExecutionMode mode, QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+                       this.mode = mode;
+               }
+
+               internal override OptionsList GetOptions ()
+               {
+                       return new OptionsList (null, mode, null, -1, null);
+               }
+       }
+
+
+       internal class ParallelMergeOptionsNode<T> : QueryOptionNode<T>
+       {
+               ParallelMergeOptions opts;
+
+               internal ParallelMergeOptionsNode (ParallelMergeOptions opts, QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+                       this.opts = opts;
+               }
+
+               internal override OptionsList GetOptions ()
+               {
+                       return new OptionsList (opts, null, null, -1, null);
+               }
+       }
+
+
+       internal class CancellationTokenNode<T> : QueryOptionNode<T>
+       {
+               CancellationToken token;
+
+               internal CancellationTokenNode (CancellationToken token, QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+                       this.token = token;
+               }
+
+               internal override OptionsList GetOptions ()
+               {
+                       return new OptionsList (null, null, token, -1, null);
+               }
+       }
+
+       internal class DegreeOfParallelismNode<T> : QueryOptionNode<T>
+       {
+               int degreeParallelism;
+
+               internal DegreeOfParallelismNode (int degreeParallelism, QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+                       this.degreeParallelism = degreeParallelism;
+               }
+
+               internal override OptionsList GetOptions ()
+               {
+                       return new OptionsList (null, null, null, degreeParallelism, null);
+               }
+       }
+
+       internal class ImplementerTokenNode<T> : QueryOptionNode<T>
+       {
+               CancellationTokenSource source;
+
+               internal ImplementerTokenNode (CancellationTokenSource token, QueryBaseNode<T> parent)
+                       : base (parent)
+               {
+                       this.source = token;
+               }
+
+               internal override OptionsList GetOptions ()
+               {
+                       return new OptionsList (null, null, null, -1, source);
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderByNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderByNode.cs
new file mode 100644 (file)
index 0000000..6261003
--- /dev/null
@@ -0,0 +1,122 @@
+#if NET_4_0
+//
+// QueryOrderByNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QueryOrderByNode<T> : QueryOrderGuardNode<T>
+       {
+               Comparison<T> comparison;
+
+               public QueryOrderByNode (QueryBaseNode<T> parent, Comparison<T> comparison)
+                       : base (parent, true)
+               {
+                       this.comparison = comparison;
+               }
+
+
+               public QueryOrderByNode (QueryOrderByNode<T> parent, Comparison<T> comparison)
+                       : base (parent.Parent, true)
+               {
+                       this.comparison = MergeComparison (parent.ComparisonFunc, comparison);
+               }
+
+               public Comparison<T> ComparisonFunc {
+                       get {
+                               return comparison;
+                       }
+               }
+
+               internal override IEnumerable<T> GetSequential ()
+               {
+                       return Parent.GetSequential ().OrderBy ((e) => e, new ComparisonComparer (comparison));
+               }
+
+               private class ComparisonComparer : IComparer<T>
+               {
+                       Comparison<T> comparison;
+
+                       internal ComparisonComparer (Comparison<T> comparison)
+                       {
+                               this.comparison = comparison;
+                       }
+
+                       int IComparer<T>.Compare (T x, T y)
+                       {
+                               return comparison (x, y);
+                       }
+               }
+
+               internal override IList<IEnumerable<T>> GetEnumerables (QueryOptions options)
+               {
+                       throw new InvalidOperationException ("Shouldn't be called");
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       int partitionCount;
+                       IList<T> aggregList = GetAggregatedList (out partitionCount);
+                       IList<T> result = ParallelQuickSort<T>.Sort (aggregList, comparison);
+
+                       OrderablePartitioner<T> partitioner = ParallelPartitioner.CreateForStrips (result, 1);
+
+                       return WrapHelper.Wrap (partitioner.GetOrderablePartitions (options.PartitionCount));
+               }
+
+               IList<T> GetAggregatedList (out int partitionCount)
+               {
+                       AggregationList<T> result = null;
+                       partitionCount = -1;
+
+                       ParallelExecuter.ProcessAndAggregate<T, IList<T>> (Parent, () => new List<T> (),
+                                                                          LocalCall,
+                                                                          (ls) => { result = new AggregationList<T> (ls); });
+
+                       return result;
+               }
+
+               IList<T> LocalCall (IList<T> list, T element)
+               {
+                       list.Add (element);
+                       return list;
+               }
+
+               static Comparison<T> MergeComparison (Comparison<T> source, Comparison<T> other)
+               {
+                       return (e1, e2) => {
+                               int result = source (e1, e2);
+                               return result == 0 ? other (e1, e2) : result;
+                       };
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderGuardNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderGuardNode.cs
new file mode 100644 (file)
index 0000000..8224460
--- /dev/null
@@ -0,0 +1,99 @@
+#if NET_4_0
+// QueryOrderGuardNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal abstract class QueryOrderGuardNode<T> : QueryStreamNode<T, T>
+       {
+               bool ensureOrder;
+
+               internal QueryOrderGuardNode (QueryBaseNode<T> parent, bool ensureOrder)
+                       : base (parent, ensureOrder)
+               {
+                       this.ensureOrder = ensureOrder;
+               }
+
+               public bool EnsureOrder {
+                       get {
+                               return ensureOrder;
+                       }
+               }
+
+               internal override IEnumerable<T> GetSequential ()
+               {
+                       return Parent.GetSequential ();
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T> (this);
+               }
+       }
+
+       internal class QueryAsUnorderedNode<T> : QueryOrderGuardNode<T>
+       {
+               internal QueryAsUnorderedNode (QueryBaseNode<T> parent)
+                       : base (parent, false)
+               {
+
+               }
+
+               internal override IList<IEnumerable<T>> GetEnumerables (QueryOptions options)
+               {
+                       return Parent.GetEnumerables (options);
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       return Parent.GetOrderedEnumerables (options);
+               }
+
+       }
+
+       internal class QueryAsOrderedNode<T> : QueryOrderGuardNode<T>
+       {
+               internal QueryAsOrderedNode (QueryBaseNode<T> parent)
+                       : base (parent, true)
+               {
+
+               }
+
+               internal override IList<IEnumerable<T>> GetEnumerables (QueryOptions options)
+               {
+                       return Parent.GetEnumerables (options);
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       return Parent.GetOrderedEnumerables (options);
+               }
+
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderedStreamNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryOrderedStreamNode.cs
new file mode 100644 (file)
index 0000000..50203fb
--- /dev/null
@@ -0,0 +1,40 @@
+#if NET_4_0
+//
+// QueryOrderedStreamNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace System.Linq
+{
+       internal abstract class QueryOrderedStreamNode<T, TParent> : QueryStreamNode<T, TParent>
+       {
+               internal QueryOrderedStreamNode (QueryBaseNode<TParent> parent, bool isIndexed)
+                       : base (parent, isIndexed)
+               {
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryReverseNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryReverseNode.cs
new file mode 100644 (file)
index 0000000..c8b87cd
--- /dev/null
@@ -0,0 +1,67 @@
+#if NET_4_0
+//
+// QueryReverseNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Threading;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QueryReverseNode<TSource> : QueryStreamNode<TSource, TSource>
+       {
+               ParallelQuery<TSource> source;
+
+               public QueryReverseNode (ParallelQuery<TSource> source)
+                       : base (source.Node, true)
+               {
+                       this.source = source;
+               }
+
+               internal override IEnumerable<TSource> GetSequential ()
+               {
+                       return Parent.GetSequential ().Reverse ();
+               }
+
+               // As stated in the doc, in this case we do nothing
+               internal override IList<IEnumerable<TSource>> GetEnumerables (QueryOptions options)
+               {
+                       return Parent.GetEnumerables (options);
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TSource>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       ReverseList<TSource> reversed = new ReverseList<TSource> (source.ToArray ());
+                       OrderablePartitioner<TSource> partitioner = ParallelPartitioner.CreateForStrips (reversed, 1);
+
+                       return WrapHelper.Wrap (partitioner.GetOrderablePartitions (options.PartitionCount));
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectManyNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectManyNode.cs
new file mode 100644 (file)
index 0000000..6c189ad
--- /dev/null
@@ -0,0 +1,122 @@
+#if NET_4_0
+//
+// QueryConcatNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class QuerySelectManyNode<TSource, TCollection, TResult> : QueryStreamNode<TResult, TSource>
+       {
+               Func<TSource, IEnumerable<TCollection>> collectionSelector;
+               Func<TSource, int, IEnumerable<TCollection>> collectionSelectorIndexed;
+               Func<TSource, TCollection, TResult> resultSelector;
+               
+               internal QuerySelectManyNode (QueryBaseNode<TSource> parent,
+                                             Func<TSource, int, IEnumerable<TCollection>> collectionSelectorIndexed,
+                                             Func<TSource, TCollection, TResult> resultSelector)
+                       : base (parent, true)
+               {
+                       this.collectionSelectorIndexed = collectionSelectorIndexed;
+                       this.resultSelector = resultSelector;
+               }
+               
+               internal QuerySelectManyNode (QueryBaseNode<TSource> parent,
+                                             Func<TSource, IEnumerable<TCollection>> collectionSelector,
+                                             Func<TSource, TCollection, TResult> resultSelector)
+                       : base (parent, false)
+               {
+                       this.collectionSelector = collectionSelector;
+                       this.resultSelector = resultSelector;
+               }
+               
+               internal override IEnumerable<TResult> GetSequential ()
+               {
+                       IEnumerable<TSource> source = Parent.GetSequential ();
+                       
+                       if (IsIndexed)
+                               return source.SelectMany (collectionSelectorIndexed, resultSelector);
+                       else
+                               return source.SelectMany (collectionSelector, resultSelector);
+               }
+               
+               internal override IList<IEnumerable<TResult>> GetEnumerables (QueryOptions options)
+               {
+                       IEnumerable<TResult>[] result = null;
+                       
+                       if (IsIndexed) {
+                               IList<IEnumerable<KeyValuePair<long, TSource>>> enumerables = Parent.GetOrderedEnumerables (options);
+                               result = new IEnumerable<TResult>[enumerables.Count];
+                               
+                               for (int i = 0; i < enumerables.Count; i++)
+                                       result[i] = GetEnumerableInternal<KeyValuePair<long, TSource>> (enumerables[i],
+                                                                                                       (kv) => collectionSelectorIndexed (kv.Value, (int)kv.Key),
+                                                                                                       (e, c) => resultSelector (e.Value, c));
+                       } else {
+                               IList<IEnumerable<TSource>> enumerables = Parent.GetEnumerables (options);
+                               result = new IEnumerable<TResult>[enumerables.Count];
+                               
+                               for (int i = 0; i < enumerables.Count; i++)
+                                       result[i] = GetEnumerableInternal<TSource> (enumerables[i],
+                                                                                   collectionSelector,
+                                                                                   (e, c) => resultSelector (e, c));
+                       }
+                       
+                       return result;
+               }
+               
+               // This one is gonna be tricky
+               internal override IList<IEnumerable<KeyValuePair<long, TResult>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               IEnumerable<TResult> GetEnumerableInternal<T> (IEnumerable<T> source,
+                                                              Func<T, IEnumerable<TCollection>> collectionner,
+                                                              Func<T, TCollection, TResult> packer)
+               {
+                       foreach (T element in source)
+                               foreach (TCollection item in collectionner (element))
+                                       yield return packer (element, item);
+               }
+               
+               IEnumerable<KeyValuePair<long, TResult>> GetOrderedEnumerableInternal (IEnumerable<KeyValuePair<long, TSource>> source,
+                                                                                      Barrier barrier)
+               {
+                       foreach (KeyValuePair<long, TSource> element in source) {
+                               IEnumerable<TCollection> collection = collectionSelectorIndexed (element.Value, (int)element.Key);
+                               
+                               foreach (TCollection item in collection)
+                                       yield return new KeyValuePair<long, TResult> (-1, resultSelector (element.Value, item));
+                       }
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySelectNode.cs
new file mode 100644 (file)
index 0000000..defbcbe
--- /dev/null
@@ -0,0 +1,97 @@
+#if NET_4_0
+//
+// QuerySelectNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QuerySelectNode<TResult, TSource> : QueryStreamNode<TResult, TSource>
+       {
+               Func<TSource, int, TResult> indexedSelector;
+               Func<TSource, TResult> selector;
+
+               internal QuerySelectNode (QueryBaseNode<TSource> parent, Func<TSource, TResult> selector)
+                       : base (parent, false)
+               {
+                       this.selector = selector;
+               }
+
+               internal QuerySelectNode (QueryBaseNode<TSource> parent, Func<TSource, int, TResult> selector)
+                       : base (parent, true)
+               {
+                       this.indexedSelector = selector;
+               }
+
+               internal override IEnumerable<TResult> GetSequential ()
+               {
+                       if (IsIndexed)
+                               return Parent.GetSequential ().Select (indexedSelector);
+                       else
+                               return Parent.GetSequential ().Select (selector);
+               }
+
+               internal override IList<IEnumerable<TResult>> GetEnumerables (QueryOptions options)
+               {
+                       if (IsIndexed) {
+                               IList<IEnumerable<KeyValuePair<long, TSource>>> sources = Parent.GetOrderedEnumerables (options);
+                               IEnumerable<TResult>[] results = new IEnumerable<TResult>[sources.Count];
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] = sources[i].Select ((e) => indexedSelector (e.Value, (int)e.Key));
+                               return results;
+                       } else {
+                               IList<IEnumerable<TSource>> sources = Parent.GetEnumerables (options);
+                               IEnumerable<TResult>[] results = new IEnumerable<TResult>[sources.Count];
+
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] = sources[i].Select (selector);
+                               return results;
+                       }
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TResult>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> sources = Parent.GetOrderedEnumerables (options);
+                       IEnumerable<KeyValuePair<long, TResult>>[] results = new IEnumerable<KeyValuePair<long, TResult>>[sources.Count];
+
+                       if (IsIndexed) {
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] = sources[i].
+                                               Select ((e) => new KeyValuePair<long, TResult> (e.Key, indexedSelector (e.Value, (int)e.Key)));
+                       } else {
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] = sources[i].
+                                               Select ((e) => new KeyValuePair<long, TResult> (e.Key, selector (e.Value)));
+                       }
+
+                       return results;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySetNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QuerySetNode.cs
new file mode 100644 (file)
index 0000000..4ea309a
--- /dev/null
@@ -0,0 +1,145 @@
+#if NET_4_0
+//
+// QueryMuxNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QuerySetNode<TSource> : QueryMuxNode<TSource, TSource, TSource>
+       {
+               readonly SetInclusion setInclusion;
+               readonly IEqualityComparer<TSource> comparer;
+
+               internal QuerySetNode (SetInclusion setInclusion, IEqualityComparer<TSource> comparer,
+                                      QueryBaseNode<TSource> first, QueryBaseNode<TSource> second)
+                       : base (first, second)
+               {
+                       this.setInclusion = setInclusion;
+                       this.comparer = comparer;
+               }
+
+               internal override IEnumerable<TSource> GetSequential ()
+               {
+                       IEnumerable<TSource> first = Parent.GetSequential ();
+                       IEnumerable<TSource> second = Second == null ? null : Second.GetSequential ();
+
+                       // We try to do some guessing based on the default
+                       switch (setInclusion) {
+                       case SetInclusionDefaults.Union:
+                               return first.Union (second, comparer);
+                       case SetInclusionDefaults.Intersect:
+                               return first.Intersect (second, comparer);
+                       case SetInclusionDefaults.Except:
+                               return first.Except (second, comparer);
+                       case SetInclusionDefaults.Distinct:
+                               return first.Distinct (comparer);
+                       }
+
+                       // Default is we return the bare source enumerable
+                       return first;
+               }
+
+               internal override IList<IEnumerable<TSource>> GetEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<TSource>> first = Parent.GetEnumerables (options);
+                       IList<IEnumerable<TSource>> second = Second.GetEnumerables (options);
+                       
+                       IEnumerable<TSource>[] result = new IEnumerable<TSource>[first.Count];
+                       ConcurrentSkipList<TSource> checker = new ConcurrentSkipList<TSource> (comparer);
+                       
+                       InitConcurrentSkipList (checker, second, (e) => e);
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = GetEnumerable<TSource> (first[i], second[i], checker, (e) => e);
+
+                       return result;
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TSource>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> first = Parent.GetOrderedEnumerables (options);
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> second = Second.GetOrderedEnumerables (options);
+
+                       IEnumerable<KeyValuePair<long, TSource>>[] result = new IEnumerable<KeyValuePair<long, TSource>>[first.Count];
+                       ConcurrentSkipList<TSource> checker = new ConcurrentSkipList<TSource> (comparer);
+                       
+                       InitConcurrentSkipList (checker, second, (e) => e.Value);
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = GetEnumerable<KeyValuePair<long, TSource>> (first[i], second[i], checker, (e) => e.Value);
+
+                       return result;
+               }
+                               
+               void InitConcurrentSkipList<TExtract> (ConcurrentSkipList<TSource> checker,
+                                                      IList<IEnumerable<TExtract>> feeds,
+                                                      Func<TExtract, TSource> extractor)
+               {
+                       if ((setInclusion & SetInclusion.Preload) == 0)
+                               return;
+                       
+                       foreach (IEnumerable<TExtract> feed in feeds)
+                               foreach (TExtract item in feed)
+                                       checker.TryAdd (extractor (item));
+               }
+
+               IEnumerable<TExtract> GetEnumerable<TExtract> (IEnumerable<TExtract> first,
+                                                              IEnumerable<TExtract> second,
+                                                              ConcurrentSkipList<TSource> checker,
+                                                              Func<TExtract, TSource> extractor)
+               {
+                       IEnumerator<TExtract> eFirst = first.GetEnumerator ();
+                       IEnumerator<TExtract> eSecond = second == null ? null : second.GetEnumerator ();
+
+                       IEnumerator<TExtract> current = eFirst;
+                       bool outInclusion = (setInclusion & SetInclusion.Out) > 0;
+                       bool preload = (setInclusion & SetInclusion.Preload) > 0;
+                       bool relaxed = (setInclusion & SetInclusion.Relaxed) > 0;
+
+                       while (current != null) {
+                               while (current.MoveNext ()) {
+                                       bool result = relaxed ?
+                                               checker.Contains (extractor (current.Current)) : checker.TryAdd (extractor (current.Current));
+
+                                       if ((result && outInclusion)
+                                           || (!result && !outInclusion))
+                                               yield return current.Current;
+                               }
+
+                               if (current == eFirst && !preload)
+                                       current = eSecond;
+                               else
+                                       break;
+                       }
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStartNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStartNode.cs
new file mode 100644 (file)
index 0000000..58ac27e
--- /dev/null
@@ -0,0 +1,110 @@
+#if NET_4_0
+//
+// QueryStartNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace System.Linq
+{
+       internal class QueryStartNode<T> : QueryBaseNode<T>
+       {
+               readonly IEnumerable<T> source;
+               readonly Partitioner<T> customPartitioner;
+
+               internal QueryStartNode (IEnumerable<T> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       this.source = source;
+               }
+
+               internal QueryStartNode (Partitioner<T> custom)
+               {
+                       if (custom == null)
+                               throw new ArgumentNullException ("custom");
+
+                       this.customPartitioner = custom;
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T> (this);
+               }
+
+               internal override IEnumerable<T> GetSequential ()
+               {
+                       if (source != null)
+                               return source;
+
+                       return WrapHelper.Wrap (customPartitioner.GetPartitions (1))[0];
+               }
+
+               internal override IList<IEnumerable<T>> GetEnumerables (QueryOptions options)
+               {
+                       if (customPartitioner != null) {
+                               return WrapHelper.Wrap (customPartitioner.GetPartitions (options.PartitionCount));
+                       }
+
+                       Partitioner<T> partitioner
+                               = (options.UseStrip) ? ParallelPartitioner.CreateForStrips (source, 1) : ParallelPartitioner.CreateBest (source);
+
+                       return WrapHelper.Wrap (partitioner.GetPartitions (options.PartitionCount));
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, T>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       OrderablePartitioner<T> partitioner = null;
+                       if (customPartitioner != null) {
+                               partitioner = customPartitioner as OrderablePartitioner<T>;
+                               if (partitioner == null)
+                                       throw new InvalidOperationException ("The partitionner you are using doesn't support ordered partitionning");
+                       } else {
+                               partitioner =
+                                       (options.UseStrip) ? ParallelPartitioner.CreateForStrips (source, 1) : ParallelPartitioner.CreateBest (source);
+                       }
+
+                       options.PartitionerSettings = Tuple.Create (partitioner.KeysOrderedAcrossPartitions,
+                                                                   partitioner.KeysOrderedInEachPartition,
+                                                                   partitioner.KeysNormalized);
+
+                       // We only support one style of partitioning at the moment.
+                       // Standard partitioners follow this style.
+                       if (options.UseStrip && (!partitioner.KeysOrderedInEachPartition || partitioner.KeysOrderedAcrossPartitions))
+                               throw new NotImplementedException ("Partitioner must have KeysOrderedInEachPartition "
+                                                                  + "and !KeysOrderedAcrossPartitions"
+                                                                  + "to be used with indexed operators");
+
+                       return WrapHelper.Wrap (partitioner.GetOrderablePartitions (options.PartitionCount));
+               }
+       }
+}
+#endif
\ No newline at end of file
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStreamNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryStreamNode.cs
new file mode 100644 (file)
index 0000000..572b2c5
--- /dev/null
@@ -0,0 +1,57 @@
+#if NET_4_0
+//
+// QueryStreamNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal abstract class QueryStreamNode<T, TParent> : QueryChildNode<T, TParent>
+       {
+               bool isIndexed;
+
+               internal QueryStreamNode (QueryBaseNode<TParent> parent, bool isIndexed)
+                       : base (parent)
+               {
+                       this.isIndexed = isIndexed;
+               }
+
+               public override void Visit (INodeVisitor visitor)
+               {
+                       visitor.Visit<T, TParent> (this);
+               }
+
+               public bool IsIndexed {
+                       get {
+                               return isIndexed;
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryWhereNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryWhereNode.cs
new file mode 100644 (file)
index 0000000..74f09d6
--- /dev/null
@@ -0,0 +1,157 @@
+#if NET_4_0
+//
+// QueryWhereNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Threading;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+
+       internal class QueryWhereNode<TSource> : QueryStreamNode<TSource, TSource>
+       {
+               Func<TSource, int, bool> indexedPredicate;
+               Func<TSource, bool> predicate;
+
+               internal QueryWhereNode (QueryBaseNode<TSource> parent, Func<TSource, bool> predicate)
+                       : base (parent, false)
+               {
+                       this.predicate = predicate;
+               }
+
+               internal QueryWhereNode (QueryBaseNode<TSource> parent, Func<TSource, int, bool> predicate)
+                       : base (parent, true)
+               {
+                       this.indexedPredicate = predicate;
+               }
+
+               internal override IEnumerable<TSource> GetSequential ()
+               {
+                       IEnumerable<TSource> parent = Parent.GetSequential ();
+
+                       if (indexedPredicate != null)
+                               return parent.Where (indexedPredicate);
+                       else
+                               return parent.Where (predicate);
+               }
+
+               internal override IList<IEnumerable<TSource>> GetEnumerables (QueryOptions options)
+               {
+                       if (IsIndexed) {
+                               IList<IEnumerable<KeyValuePair<long, TSource>>> sources = Parent.GetOrderedEnumerables (options);
+                               IEnumerable<TSource>[] results = new IEnumerable<TSource>[sources.Count];
+
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] =
+                                               sources[i].Where ((e) => indexedPredicate (e.Value, (int)e.Key)).Select ((e) => e.Value);
+                               return results;
+                       } else {
+                               IList<IEnumerable<TSource>> sources = Parent.GetEnumerables (options);
+                               IEnumerable<TSource>[] results = new IEnumerable<TSource>[sources.Count];
+
+                               for (int i = 0; i < results.Length; i++)
+                                       results[i] = sources[i].Where (predicate);
+                               return results;
+                       }
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TSource>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TSource>>> sources = Parent.GetOrderedEnumerables (options);
+                       IEnumerable<KeyValuePair<long, TSource>>[] results = new IEnumerable<KeyValuePair<long, TSource>>[sources.Count];
+
+                       Tuple<TSource, long, bool>[] store = new Tuple<TSource, long, bool>[results.Length];
+                       long lastIndex = 0;
+
+                       Barrier barrier = new Barrier (results.Length, delegate (Barrier b) {
+                               // Sort the store
+                               Array.Sort (store, ArraySortMethod);
+
+                               // Reassign a good index
+                               int i = 0;
+
+                               for (i = 0; i < store.Length && store[i].Item3; i++) {
+                                       Tuple<TSource, long, bool> old = store[i];
+                                       store[i] = Tuple.Create (old.Item1, lastIndex + i, old.Item3);
+                               }
+
+                               // Update lastIndex for next round
+                               lastIndex += i;
+                       });
+
+                       for (int j = 0; j < results.Length; j++)
+                               results[j] = GetEnumerator (sources[j], barrier, store, j);
+
+                       return results;
+               }
+
+               static int ArraySortMethod (Tuple<TSource, long, bool> lhs, Tuple<TSource, long, bool> rhs)
+               {
+                       if (lhs.Item3 && !rhs.Item3)
+                               return -1;
+                       if (!lhs.Item3 && rhs.Item3)
+                               return 1;
+                       if (!lhs.Item3 && !rhs.Item3)
+                               return 0;
+
+                       return (lhs.Item2 < rhs.Item2) ? -1 : 1;
+               }
+
+               IEnumerable<KeyValuePair<long, TSource>> GetEnumerator (IEnumerable<KeyValuePair<long, TSource>> source,
+                                                                       Barrier barrier,
+                                                                       Tuple<TSource, long, bool>[] store, int index)
+               {
+                       IEnumerator<KeyValuePair<long, TSource>> current = source.GetEnumerator ();
+                       bool result;
+
+                       while (current.MoveNext ()) {
+                               KeyValuePair<long, TSource> curr = current.Current;
+
+                               if (IsIndexed)
+                                       result = indexedPredicate (curr.Value, (int)curr.Key);
+                               else
+                                       result = predicate (curr.Value);
+
+                               store[index] = Tuple.Create (curr.Value, curr.Key, result);
+                               barrier.SignalAndWait ();
+
+                               Tuple<TSource, long, bool> value = store [index];
+
+                               if (value.Item3)
+                                       yield return new KeyValuePair<long, TSource> (value.Item2, value.Item1);
+
+                               // Reset
+                               store[index] = Tuple.Create (default (TSource), long.MaxValue, false);
+                       }
+
+                       // Remove our participation
+                       barrier.RemoveParticipant ();
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryZipNode.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/QueryZipNode.cs
new file mode 100644 (file)
index 0000000..8268db5
--- /dev/null
@@ -0,0 +1,135 @@
+#if NET_4_0
+//
+// QueryZipNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Linq;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class QueryZipNode<TFirst, TSecond, TResult> : QueryMuxNode<TFirst, TSecond, TResult>
+       {
+               Func<TFirst, TSecond, TResult> resultSelector;
+
+               public QueryZipNode (Func<TFirst, TSecond, TResult> resultSelector, QueryBaseNode<TFirst> first, QueryBaseNode<TSecond> second)
+                       : base (first, second)
+               {
+                       this.resultSelector = resultSelector;
+               }
+
+               internal override IEnumerable<TResult> GetSequential ()
+               {
+                       IEnumerable<TFirst> first = Parent.GetSequential ();
+                       IEnumerable<TSecond> second = Second.GetSequential ();
+
+                       return first.Zip (second, resultSelector);
+               }
+
+               internal override IList<IEnumerable<TResult>> GetEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<TFirst>> first = Parent.GetEnumerables (options);
+                       IList<IEnumerable<TSecond>> second = Second.GetEnumerables (options);
+
+                       if (first.Count != second.Count)
+                               throw new InvalidOperationException ("Internal size mismatch");
+
+                       IEnumerable<TResult>[] result = new IEnumerable<TResult>[first.Count];
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = GetEnumerable (first[i], second[i]);
+
+                       return result;
+               }
+
+               IEnumerable<TResult> GetEnumerable (IEnumerable<TFirst> first, IEnumerable<TSecond> second)
+               {
+                       IEnumerator<TFirst> eFirst = first.GetEnumerator ();
+                       IEnumerator<TSecond> eSecond = second.GetEnumerator ();
+
+                       while (eFirst.MoveNext ()) {
+                               if (!eSecond.MoveNext ())
+                                       yield break;
+
+                               yield return resultSelector (eFirst.Current, eSecond.Current);
+                       }
+               }
+
+               internal override IList<IEnumerable<KeyValuePair<long, TResult>>> GetOrderedEnumerables (QueryOptions options)
+               {
+                       IList<IEnumerable<KeyValuePair<long, TFirst>>> first = Parent.GetOrderedEnumerables (options);
+                       IList<IEnumerable<KeyValuePair<long, TSecond>>> second = Second.GetOrderedEnumerables (options);
+
+                       if (first.Count != second.Count)
+                               throw new InvalidOperationException ("Internal size mismatch");
+
+                       IEnumerable<KeyValuePair<long, TResult>>[] result = new IEnumerable<KeyValuePair<long, TResult>>[first.Count];
+
+                       KeyValuePair<long, TFirst>[] store1 = new KeyValuePair<long, TFirst>[result.Length];
+                       KeyValuePair<long, TSecond>[] store2 = new KeyValuePair<long, TSecond>[result.Length];
+
+                       Barrier barrier = new Barrier (result.Length, delegate {
+                               Array.Sort (store1, (e1, e2) => e1.Key.CompareTo (e2.Key));
+                               Array.Sort (store2, (e1, e2) => e1.Key.CompareTo (e2.Key));
+                       });
+
+                       for (int i = 0; i < result.Length; i++)
+                               result[i] = GetEnumerable (first[i], second[i], i, store1, store2, barrier);
+
+                       return result;
+               }
+
+               IEnumerable<KeyValuePair<long, TResult>> GetEnumerable (IEnumerable<KeyValuePair<long, TFirst>> first,
+                                                                       IEnumerable<KeyValuePair<long, TSecond>> second,
+                                                                       int index,
+                                                                       KeyValuePair<long, TFirst>[] store1,
+                                                                       KeyValuePair<long, TSecond>[] store2,
+                                                                       Barrier barrier)
+               {
+                       IEnumerator<KeyValuePair<long, TFirst>> eFirst = first.GetEnumerator ();
+                       IEnumerator<KeyValuePair<long, TSecond>> eSecond = second.GetEnumerator ();
+
+                       while (eFirst.MoveNext ()) {
+                               if (!eSecond.MoveNext ())
+                                       break;
+
+                               store1[index] = eFirst.Current;
+                               store2[index] = eSecond.Current;
+
+                               barrier.SignalAndWait ();
+
+                               yield return new KeyValuePair<long, TResult> (store1[index].Key,
+                                                                                resultSelector (store1[index].Value, store2[index].Value));
+                       }
+
+                       barrier.RemoveParticipant ();
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/QueryNodes/WrapHelper.cs b/mcs/class/System.Core/System.Linq/Internal/QueryNodes/WrapHelper.cs
new file mode 100644 (file)
index 0000000..a44d61a
--- /dev/null
@@ -0,0 +1,63 @@
+#if NET_4_0
+//
+// WrapHelper.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Linq;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class WrapHelper
+       {
+               class EnumeratorWrapper<TEnum> : IEnumerable<TEnum>
+               {
+                       IEnumerator<TEnum> enumerator;
+
+                       public EnumeratorWrapper (IEnumerator<TEnum> enumerator)
+                       {
+                               this.enumerator = enumerator;
+                       }
+
+                       public IEnumerator<TEnum> GetEnumerator ()
+                       {
+                               return enumerator;
+                       }
+
+                       IEnumerator IEnumerable.GetEnumerator ()
+                       {
+                               return (IEnumerator)enumerator;
+                       }
+               }
+
+               internal static IList<IEnumerable<TEnum>> Wrap<TEnum> (IList<IEnumerator<TEnum>> src)
+               {
+                       return src.Select ((e) => (IEnumerable<TEnum>)new EnumeratorWrapper<TEnum> (e)).ToArray ();
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/RangeList.cs b/mcs/class/System.Core/System.Linq/Internal/RangeList.cs
new file mode 100644 (file)
index 0000000..43e7ed2
--- /dev/null
@@ -0,0 +1,125 @@
+#if NET_4_0
+//
+// RangeList.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class RangeList : IList<int>
+       {
+               readonly int start;
+               readonly int count;
+
+               public RangeList (int start, int count)
+               {
+                       this.start = start;
+                       this.count = count;
+               }
+
+               public int IndexOf (int item)
+               {
+                       if (!Contains(item))
+                               return -1;
+
+                       return item - start;
+               }
+
+               public void Insert (int index, int item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public int this[int index] {
+                       get {
+                               if (start + index <= count)
+                                       return start + index;
+                               else
+                                       return -1;
+                       }
+                       set {
+                               throw new NotImplementedException();
+                       }
+               }
+
+               public void Add (int item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Contains (int item)
+               {
+                       return start <= item && item <= start + count - 1;
+               }
+
+               public void CopyTo (int[] array, int arrayIndex)
+               {
+                       int counter = start;
+                       for (int i = arrayIndex; i < array.Length && i < (i - arrayIndex) + count; i++)
+                               array[i] = counter++;
+               }
+
+               public bool Remove (int item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               IEnumerator<int> IEnumerable<int>.GetEnumerator ()
+               {
+                       return null;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return null;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/RepeatList.cs b/mcs/class/System.Core/System.Linq/Internal/RepeatList.cs
new file mode 100644 (file)
index 0000000..35bbd10
--- /dev/null
@@ -0,0 +1,119 @@
+#if NET_4_0
+//
+// RepeatList.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class RepeatList<T> : IList<T>
+       {
+               readonly int count;
+               readonly T element;
+
+               public RepeatList (T element, int count)
+               {
+                       this.element = element;
+                       this.count = count;
+               }
+
+               public int IndexOf (T item)
+               {
+                       // No real index, we may just be interested if the value is different from -1
+                       return Contains(item) ? 1 : -1;
+               }
+
+               public void Insert (int index, T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public T this[int index] {
+                       get {
+                               return index < count ? element : default(T);
+                       }
+                       set {
+                               throw new NotImplementedException();
+                       }
+               }
+
+               public void Add (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Contains (T item)
+               {
+                       return item.Equals(element);
+               }
+
+               public void CopyTo (T[] array, int arrayIndex)
+               {
+                       for (int i = arrayIndex; i < array.Length && i < (i - arrayIndex) + count; i++)
+                               array[i] = element;
+               }
+
+               public bool Remove (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+               {
+                       return null;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return null;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/ReverseList.cs b/mcs/class/System.Core/System.Linq/Internal/ReverseList.cs
new file mode 100644 (file)
index 0000000..b5ca7d0
--- /dev/null
@@ -0,0 +1,119 @@
+#if NET_4_0
+//
+// QueryReverseNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System.Linq;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace System.Linq
+{
+       internal class ReverseList<T> : IList<T>
+       {
+               readonly IList<T> backend;
+               readonly int count;
+
+               internal ReverseList (IList<T> backend)
+               {
+                       this.backend = backend;
+                       this.count = backend.Count;
+               }
+
+               public int IndexOf (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Insert (int index, T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void RemoveAt (int index)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public T this[int index] {
+                       get {
+                               return backend[count - 1 - index];
+                       }
+                       set {
+                               throw new NotImplementedException();
+                       }
+               }
+
+               public void Add (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void Clear ()
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Contains (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public void CopyTo (T[] array, int arrayIndex)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public bool Remove (T item)
+               {
+                       throw new NotImplementedException();
+               }
+
+               public int Count {
+                       get {
+                               return count;
+                       }
+               }
+
+               public bool IsReadOnly {
+                       get {
+                               return true;
+                       }
+               }
+
+               IEnumerator<T> IEnumerable<T>.GetEnumerator ()
+               {
+                       return null;
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return null;
+               }
+       }
+}
+
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/StripPartitioner.cs b/mcs/class/System.Core/System.Linq/Internal/StripPartitioner.cs
new file mode 100644 (file)
index 0000000..699cb09
--- /dev/null
@@ -0,0 +1,62 @@
+#if NET_4_0
+//
+// StripPartitioner.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       internal class StripPartitioner<T> : OrderablePartitioner<T>
+       {
+               IList<T> source;
+
+               public StripPartitioner (IList<T> source) : base (true, false, true)
+               {
+                       this.source = source;
+               }
+
+               public override IList<IEnumerator<KeyValuePair<long, T>>> GetOrderablePartitions (int partitionCount)
+               {
+                       IEnumerator<KeyValuePair<long, T>>[] array = new IEnumerator<KeyValuePair<long, T>>[partitionCount];
+                       for (int i = 0; i < array.Length; i++)
+                               array[i] = GetStripEnumerator (i, partitionCount);
+
+                       return array;
+               }
+
+               IEnumerator<KeyValuePair<long, T>> GetStripEnumerator (int start, int partitionCount)
+               {
+                       for (int i = start; i < source.Count; i += partitionCount) {
+                               //Console.WriteLine ("Num {0} yielding [{1} : {2}]", start, i, source[i]);
+                               yield return new KeyValuePair<long, T> (i, source [i]);
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/Visitors/ChangeLog b/mcs/class/System.Core/System.Linq/Internal/Visitors/ChangeLog
new file mode 100644 (file)
index 0000000..55e3ece
--- /dev/null
@@ -0,0 +1,7 @@
+2010-04-15  Jérémie Laval  <jeremie.laval@gmail.com>
+
+       * INodeVisitor.cs:
+       * IVisitableNode.cs:
+       * QueryCheckerVisitor.cs:
+       * QueryOptions.cs: First check-in of PLinq
+
diff --git a/mcs/class/System.Core/System.Linq/Internal/Visitors/INodeVisitor.cs b/mcs/class/System.Core/System.Linq/Internal/Visitors/INodeVisitor.cs
new file mode 100644 (file)
index 0000000..1b056fd
--- /dev/null
@@ -0,0 +1,43 @@
+#if NET_4_0
+//
+// INodeVisitor.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace System.Linq
+{
+       internal interface INodeVisitor
+       {
+               void Visit<T> (QueryBaseNode<T> node);
+               void Visit<U, V> (QueryChildNode<U, V> node);
+               void Visit<T> (QueryOptionNode<T> node);
+               void Visit<T> (QueryStartNode<T> node);
+               void Visit<T, TParent> (QueryStreamNode<T, TParent> node);
+               void Visit<T> (QueryOrderGuardNode<T> node);
+               void Visit<TFirst, TSecond, TResult> (QueryMuxNode<TFirst, TSecond, TResult> node);
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/Visitors/IVisitableNode.cs b/mcs/class/System.Core/System.Linq/Internal/Visitors/IVisitableNode.cs
new file mode 100644 (file)
index 0000000..5d7326f
--- /dev/null
@@ -0,0 +1,37 @@
+#if NET_4_0
+//
+// IVisitableNode.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+
+namespace System.Linq
+{
+       internal interface IVisitableNode
+       {
+               void Visit (INodeVisitor visitor);
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/Visitors/QueryCheckerVisitor.cs b/mcs/class/System.Core/System.Linq/Internal/Visitors/QueryCheckerVisitor.cs
new file mode 100644 (file)
index 0000000..df5660f
--- /dev/null
@@ -0,0 +1,162 @@
+#if NET_4_0
+//
+// QueryCheckerVisitor.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+
+namespace System.Linq
+{
+       using OptionsList = Tuple<ParallelMergeOptions?, ParallelExecutionMode?, CancellationToken?, int, CancellationTokenSource>;
+
+       internal class QueryCheckerVisitor : INodeVisitor
+       {
+               // Information gathering
+               ParallelMergeOptions? options = null;
+               ParallelExecutionMode? mode = null;
+               CancellationToken? token = null;
+               int? degreeOfParallelism = null;
+               bool useStrip;
+               CancellationToken implementerToken = CancellationToken.None;
+
+               int partitionCount;
+               bool? behindOrderGuard = null;
+
+               internal QueryCheckerVisitor (int partitionCount)
+               {
+                       this.partitionCount = partitionCount;
+               }
+
+               #region INodeVisitor implementation
+               public void Visit<T> (QueryBaseNode<T> node)
+               {
+                       // Nothing to do atm. Later we can check if the node is a
+                       // Take or a Skip and set accordingly useStrip
+               }
+
+               public void Visit<U, V> (QueryChildNode<U, V> node)
+               {
+                       node.Parent.Visit (this);
+               }
+
+               public void Visit<T> (QueryOptionNode<T> node)
+               {
+                       MergeOptions (node.GetOptions ());
+
+                       Visit<T, T> ((QueryChildNode<T, T>)node);
+               }
+
+               public void Visit<T> (QueryStartNode<T> node)
+               {
+                       if (behindOrderGuard == null)
+                               behindOrderGuard = false;
+                       if (degreeOfParallelism != null)
+                               partitionCount = degreeOfParallelism.Value;
+               }
+
+               public void Visit<T, TParent> (QueryStreamNode<T, TParent> node)
+               {
+                       if (node.IsIndexed)
+                               useStrip = true;
+
+                       Visit<T, TParent> ((QueryChildNode<T, TParent>)node);
+               }
+
+               public void Visit<T> (QueryOrderGuardNode<T> node)
+               {
+                       if (node.EnsureOrder && behindOrderGuard == null)
+                               behindOrderGuard = true;
+               }
+
+               public void Visit<TFirst, TSecond, TResult> (QueryMuxNode<TFirst, TSecond, TResult> node)
+               {
+
+                       Visit<TResult, TFirst> ((QueryChildNode<TResult, TFirst>)node);
+               }
+               #endregion
+
+               internal QueryOptions Options {
+                       get {
+                               return new QueryOptions (options, mode, token == null ? CancellationToken.None : token.Value,
+                                                        useStrip, behindOrderGuard, partitionCount, implementerToken);
+                       }
+               }
+
+               internal bool UseStrip {
+                       get {
+                               return useStrip;
+                       }
+               }
+
+               internal bool BehindOrderGuard {
+                       get {
+                               return behindOrderGuard.Value;
+                       }
+               }
+
+               void MergeOptions (OptionsList list)
+               {
+                       if (list.Item1 != null) {
+                               if (options == null)
+                                       options = list.Item1;
+                               else
+                                       Throw ("WithMergeOptions");
+                       }
+
+                       if (list.Item2 != null) {
+                               if (mode == null)
+                                       mode = list.Item2;
+                               else
+                                       Throw ("WithExecutionMode");
+                       }
+
+                       if (list.Item3 != null) {
+                               if (token == null)
+                                       token = list.Item3;
+                               else
+                                       Throw ("WithCancellationToken");
+                       }
+
+                       if (list.Item4 != -1) {
+                               if (degreeOfParallelism == null)
+                                       degreeOfParallelism = list.Item4;
+                               else
+                                       Throw ("WithDegreeOfParallelism");
+                       }
+
+                       // That one is treated specially
+                       if (list.Item5 != null) {
+                               implementerToken = implementerToken.Chain (list.Item5);
+                       }
+               }
+
+               void Throw (string methName)
+               {
+                       throw new InvalidOperationException ("You can't have more than one " + methName + " node in a query");
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/Internal/Visitors/QueryOptions.cs b/mcs/class/System.Core/System.Linq/Internal/Visitors/QueryOptions.cs
new file mode 100644 (file)
index 0000000..f6d0702
--- /dev/null
@@ -0,0 +1,71 @@
+#if NET_4_0
+//
+// QueryOptions.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+
+namespace System.Linq
+{
+       internal class QueryOptions
+       {
+               public ParallelMergeOptions? Options;
+               public ParallelExecutionMode? Mode;
+               public CancellationToken Token;
+               /* This token is to be used by some operator (like Take) to tell that
+                * the execution of the query can be prematurly stopped
+                *
+                * It is set when passing QueryOptions to the different node's Get method
+                * and ParallelExecuter should check after the call to this method is this guy has been
+                * set. Operator may chain up multiple cancellation token that way.
+                * When checking for this token, the task body should simply return.
+                */
+               public CancellationToken ImplementerToken;
+               public bool UseStrip;
+               public bool? BehindOrderGuard;
+               public int PartitionCount;
+               public Tuple<bool, bool, bool> PartitionerSettings;
+
+               public QueryOptions (ParallelMergeOptions? options,
+                                    ParallelExecutionMode? mode,
+                                    CancellationToken token,
+                                    bool useStrip,
+                                    bool? behindOrderGuard,
+                                    int partitionCount,
+                                    CancellationToken implementerToken)
+               {
+                       Options = options;
+                       Mode = mode;
+                       Token = token;
+                       UseStrip = useStrip;
+                       BehindOrderGuard = behindOrderGuard;
+                       PartitionCount = partitionCount;
+                       PartitionerSettings = null;
+                       ImplementerToken = implementerToken;
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/OrderedParallelQuery.cs b/mcs/class/System.Core/System.Linq/OrderedParallelQuery.cs
new file mode 100644 (file)
index 0000000..a8b80b7
--- /dev/null
@@ -0,0 +1,54 @@
+#if NET_4_0
+//
+// ParallelQuery.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       // Only returned after OrderBy and ThenBy.
+       public class OrderedParallelQuery<TSource> : ParallelQuery<TSource>
+       {
+               QueryOrderByNode<TSource> node;
+
+               internal OrderedParallelQuery (QueryOrderByNode<TSource> node)
+                       : base (node)
+               {
+                       this.node = node;
+               }
+
+               internal new QueryOrderByNode<TSource> Node {
+                       get {
+                               return node;
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/ParallelEnumerable.cs b/mcs/class/System.Core/System.Linq/ParallelEnumerable.cs
new file mode 100644 (file)
index 0000000..de5dd6c
--- /dev/null
@@ -0,0 +1,2113 @@
+#if NET_4_0
+//
+// ParallelEnumerable.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       public static class ParallelEnumerable
+       {
+               #region Range & Repeat
+               public static ParallelQuery<int> Range (int start, int count)
+               {
+                       if (int.MaxValue - start < count)
+                               throw new ArgumentOutOfRangeException ("count", "start + count - 1 is larger than Int32.MaxValue");
+                       if (count < 0)
+                               throw new ArgumentOutOfRangeException ("count", "count is less than 0");
+
+                       return (new RangeList (start, count)).AsParallel ();
+               }
+
+               public static ParallelQuery<TResult> Repeat<TResult> (TResult obj, int count)
+               {
+                       if (count < 0)
+                               throw new ArgumentOutOfRangeException ("count", "count is less than 0");
+
+                       return (new RepeatList<TResult> (obj, count)).AsParallel ();
+               }
+               #endregion
+
+               #region Empty
+               public static ParallelQuery<TResult> Empty<TResult> ()
+               {
+                       return Repeat<TResult> (default (TResult), 0);
+               }
+               #endregion
+
+               #region AsParallel
+               public static ParallelQuery<TSource> AsParallel<TSource> (this IEnumerable<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
+               }
+
+               public static ParallelQuery<TSource> AsParallel<TSource> (this Partitioner<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
+               }
+
+               public static ParallelQuery AsParallel (this IEnumerable source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<object> (new QueryStartNode<object> (source.Cast<object> ()));
+               }
+
+               public static IEnumerable<TSource> AsEnumerable<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.AsSequential ();
+               }
+
+               public static IEnumerable<TSource> AsSequential<TSource> (      this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Node.GetSequential ();
+               }
+               #endregion
+
+               #region AsOrdered / AsUnordered
+               public static ParallelQuery<TSource> AsOrdered<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new QueryAsOrderedNode<TSource> (source.Node));
+               }
+
+               public static ParallelQuery<TSource> AsUnordered<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new QueryAsUnorderedNode<TSource> (source.Node));
+               }
+
+               public static ParallelQuery AsOrdered (ParallelQuery source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.TypedQuery.AsOrdered ();
+               }
+               #endregion
+
+               #region With*
+               public static ParallelQuery<TSource> WithExecutionMode<TSource> (this ParallelQuery<TSource> source,
+                                                                                ParallelExecutionMode executionMode)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new ParallelExecutionModeNode<TSource> (executionMode, source.Node));
+               }
+
+               public static ParallelQuery<TSource> WithCancellation<TSource> (this ParallelQuery<TSource> source,
+                                                                               CancellationToken cancellationToken)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new CancellationTokenNode<TSource> (cancellationToken, source.Node));
+               }
+
+               public static ParallelQuery<TSource> WithMergeOptions<TSource> (this ParallelQuery<TSource> source,
+                                                                               ParallelMergeOptions mergeOptions)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new ParallelMergeOptionsNode<TSource> (mergeOptions, source.Node));
+               }
+
+               public static ParallelQuery<TSource> WithDegreeOfParallelism<TSource> (this ParallelQuery<TSource> source,
+                                                                                      int degreeParallelism)
+               {
+                       if (degreeParallelism < 1 || degreeParallelism > 63)
+                               throw new ArgumentException ("degreeOfParallelism is less than 1 or greater than 63", "degreeParallelism");
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new DegreeOfParallelismNode<TSource> (degreeParallelism, source.Node));
+               }
+
+               internal static ParallelQuery<TSource> WithImplementerToken<TSource> (this ParallelQuery<TSource> source,
+                                                                                     CancellationTokenSource token)
+               {
+                       return new ParallelQuery<TSource> (new ImplementerTokenNode<TSource> (token, source.Node));
+               }
+               #endregion
+
+               #region Select
+               public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (selector == null)
+                               throw new ArgumentNullException ("selector");
+
+                       return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
+               }
+
+               public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, int, TResult> selector)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (selector == null)
+                               throw new ArgumentNullException ("selector");
+
+                       return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
+               }
+               #endregion
+               
+               #region SelectMany
+               public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
+                                                                                  Func<TSource, IEnumerable<TResult>> selector)
+               {
+                       return source.SelectMany (selector, (s, e) => e);
+               }
+
+               public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
+                                                                                  Func<TSource, int, IEnumerable<TResult>> selector)
+               {
+                       return source.SelectMany (selector, (s, e) => e);
+               }
+               
+               public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
+                                                                                               Func<TSource, IEnumerable<TCollection>> collectionSelector,
+                                                                                               Func<TSource, TCollection, TResult> resultSelector)
+               {
+                       return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
+                                                                                                                  collectionSelector,
+                                                                                                                  resultSelector));
+               }
+               
+               public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
+                                                                                               Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
+                                                                                               Func<TSource, TCollection, TResult> resultSelector)
+               {
+                       return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
+                                                                                                                  collectionSelector,
+                                                                                                                  resultSelector));
+               }
+               #endregion
+
+               #region Where
+               public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
+               }
+
+               public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
+               }
+               #endregion
+
+               #region Aggregate
+               public static TSource Aggregate<TSource> (this ParallelQuery<TSource> source, Func<TSource, TSource, TSource> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Aggregate<TSource, TSource, TSource> ((Func<TSource>)null,
+                                                                           func,
+                                                                           func,
+                                                                           (e) => e);
+               }
+
+               public static TAccumulate Aggregate<TSource, TAccumulate> (this ParallelQuery<TSource> source,
+                                                                            TAccumulate seed,
+                                                                            Func<TAccumulate, TSource, TAccumulate> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Aggregate (seed, func, (e) => e);
+               }
+
+               public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
+                                                                                 TAccumulate seed,
+                                                                                 Func<TAccumulate, TSource, TAccumulate> func,
+                                                                                 Func<TAccumulate, TResult> resultSelector)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+                       if (resultSelector == null)
+                               throw new ArgumentNullException ("resultSelector");
+
+                       TAccumulate accumulator = seed;
+
+                       foreach (TSource value in source)
+                               accumulator = func (accumulator, value);
+
+                       return resultSelector (accumulator);
+               }
+
+               public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
+                                                                                 TAccumulate seed,
+                                                                                 Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
+                                                                                 Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
+                                                                                 Func<TAccumulate, TResult> resultSelector)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (updateAccumulatorFunc == null)
+                               throw new ArgumentNullException ("updateAccumulatorFunc");
+                       if (combineAccumulatorsFunc == null)
+                               throw new ArgumentNullException ("combineAccumulatorsFunc");
+                       if (resultSelector == null)
+                               throw new ArgumentNullException ("resultSelector");
+
+                       return source.Aggregate (() => seed, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector);
+               }
+
+               public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
+                                                                                 Func<TAccumulate> seedFunc,
+                                                                                 Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
+                                                                                 Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
+                                                                                 Func<TAccumulate, TResult> resultSelector)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (seedFunc == null)
+                               throw new ArgumentNullException ("seedFunc");
+                       if (updateAccumulatorFunc == null)
+                               throw new ArgumentNullException ("updateAccumulatorFunc");
+                       if (combineAccumulatorsFunc == null)
+                               throw new ArgumentNullException ("combineAccumulatorsFunc");
+                       if (resultSelector == null)
+                               throw new ArgumentNullException ("resultSelector");
+
+                       TAccumulate accumulator = default (TAccumulate);
+
+                       ParallelExecuter.ProcessAndAggregate<TSource, TAccumulate> (source.Node, seedFunc, updateAccumulatorFunc, (list) => {
+                               accumulator = list [0];
+                               for (int i = 1; i < list.Count; i++)
+                                       accumulator = combineAccumulatorsFunc (accumulator, list[i]);
+                       });
+
+                       return resultSelector (accumulator);;
+               }
+               #endregion
+
+               #region ForAll
+               public static void ForAll<TSource> (this ParallelQuery<TSource> source, Action<TSource> action)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (action == null)
+                               throw new ArgumentNullException ("action");
+
+                       ParallelExecuter.ProcessAndBlock (source.Node, action);
+               }
+               #endregion
+
+               #region OrderBy
+               public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                             Func<TSource, TKey> keySelector,
+                                                                                             IComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
+
+                       return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
+               }
+
+               public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                             Func<TSource, TKey> keySelector)
+               {
+                       return OrderByDescending (source, keySelector, Comparer<TKey>.Default);
+               }
+
+               public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                   Func<TSource, TKey> keySelector)
+               {
+                       return OrderBy (source, keySelector, Comparer<TKey>.Default);
+               }
+
+               public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                   Func<TSource, TKey> keySelector,
+                                                                                   IComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
+
+                       return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
+               }
+               #endregion
+
+               #region ThenBy
+               public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
+                                                                                  Func<TSource, TKey> keySelector)
+               {
+                       return ThenBy (source, keySelector, Comparer<TKey>.Default);
+               }
+
+               public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
+                                                                                  Func<TSource, TKey> keySelector,
+                                                                                  IComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
+
+                       return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
+               }
+
+               public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
+                                                                                            Func<TSource, TKey> keySelector)
+               {
+                       return ThenByDescending (source, keySelector, Comparer<TKey>.Default);
+               }
+
+               public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
+                                                                                            Func<TSource, TKey> keySelector,
+                                                                                            IComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
+
+                       return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
+               }
+               #endregion
+
+               #region All
+               public static bool All<TSource> (ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       CancellationTokenSource src = new CancellationTokenSource ();
+                       ParallelQuery<TSource> innerQuery = source.WithImplementerToken (src);
+
+                       bool result = true;
+                       innerQuery.ForAll ((e) => {
+                               if (!predicate (e)) {
+                                       result = false;
+                                       src.Cancel ();
+                               }
+                       });
+
+                       return result;
+               }
+               #endregion
+
+               #region Any
+               public static bool Any<TSource> (this ParallelQuery<TSource> source)
+               {
+                       return Any<TSource> (source, (_) => true);
+               }
+
+               public static bool Any<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return !source.All ((e) => !predicate (e));
+               }
+               #endregion
+
+               #region Contains
+               public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value)
+               {
+                       return Contains<TSource> (source, value, EqualityComparer<TSource>.Default);
+               }
+
+               public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       return Any<TSource> (source, (e) => comparer.Equals (value));
+               }
+               #endregion
+
+               #region SequenceEqual
+               public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
+                                                          ParallelQuery<TSource> second)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+
+                       return first.SequenceEqual (second, EqualityComparer<TSource>.Default);
+               }
+
+               public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
+                                                          ParallelQuery<TSource> second,
+                                                          IEqualityComparer<TSource> comparer)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       CancellationTokenSource source = new CancellationTokenSource ();
+                       ParallelQuery<bool> innerQuery
+                               = first.Zip (second, (e1, e2) => comparer.Equals (e1, e2)).Where ((e) => !e).WithImplementerToken (source);
+
+                       bool result = true;
+
+                       innerQuery.ForAll ((value) => {
+                               result = false;
+                               source.Cancel ();
+                       });
+
+                       return result;
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
+                                                             IEnumerable<TSource> second,
+                                                             IEqualityComparer<TSource> comparer)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               #endregion
+               
+               #region GroupBy
+               public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (  this ParallelQuery<TSource> source,
+                                                                                             Func<TSource, TKey> keySelector)
+               {
+                       return source.GroupBy (keySelector, EqualityComparer<TKey>.Default);
+               }
+               
+               public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (  this ParallelQuery<TSource> source,
+                                                                                             Func<TSource, TKey> keySelector,
+                                                                                             IEqualityComparer<TKey> comparer)
+               {
+                       return source.GroupBy (keySelector, (e) => e, comparer);
+               }
+               
+               public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                                        Func<TSource, TKey> keySelector,
+                                                                                                        Func<TSource, TElement> elementSelector)
+               {
+                       return source.GroupBy (keySelector, elementSelector, EqualityComparer<TKey>.Default);
+               }
+               
+               public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (this ParallelQuery<TSource> source,
+                                                                                     Func<TSource, TKey> keySelector,
+                                                                                     Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
+               {
+                       return source.GroupBy (keySelector)
+                               .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
+               }
+               
+               public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                                        Func<TSource, TKey> keySelector,
+                                                                                                        Func<TSource, TElement> elementSelector,
+                                                                                                        IEqualityComparer<TKey> comparer)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
+                                                                                               Func<TSource, TKey> keySelector,
+                                                                                               Func<TSource, TElement> elementSelector,
+                                                                                               Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
+               {
+                       return source.GroupBy (keySelector, elementSelector)
+                               .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
+               }
+               
+               public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (  this ParallelQuery<TSource> source,
+                                                                                     Func<TSource, TKey> keySelector,
+                                                                                     Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
+                                                                                     IEqualityComparer<TKey> comparer)
+               {
+                       return source.GroupBy (keySelector, comparer)
+                               .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
+               }
+               
+               public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
+                                                                                               Func<TSource, TKey> keySelector,
+                                                                                               Func<TSource, TElement> elementSelector,
+                                                                                               Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
+                                                                                               IEqualityComparer<TKey> comparer)
+               {
+                       return source.GroupBy (keySelector, elementSelector, comparer)
+                               .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
+               }
+               #endregion
+
+               #region GroupJoin
+               public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
+                                                                                              ParallelQuery<TInner> inner,
+                                                                                              Func<TOuter, TKey> outerKeySelector,
+                                                                                              Func<TInner, TKey> innerKeySelector,
+                                                                                              Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
+               {
+                       return outer.GroupJoin (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
+               }
+               
+               public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
+                                                                                              ParallelQuery<TInner> inner,
+                                                                                              Func<TOuter, TKey> outerKeySelector,
+                                                                                              Func<TInner, TKey> innerKeySelector,
+                                                                                              Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
+                                                                                              IEqualityComparer<TKey> comparer)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
+                                                                                              IEnumerable<TInner> inner,
+                                                                                              Func<TOuter, TKey> outerKeySelector,
+                                                                                              Func<TInner, TKey> innerKeySelector,
+                                                                                              Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
+               {
+                       throw new NotSupportedException ();
+               }
+               
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
+                                                                                              IEnumerable<TInner> inner,
+                                                                                              Func<TOuter, TKey> outerKeySelector,
+                                                                                              Func<TInner, TKey> innerKeySelector,
+                                                                                              Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
+                                                                                              IEqualityComparer<TKey> comparer)
+               {
+                       throw new NotImplementedException ();
+               }
+               #endregion
+
+               #region ElementAt
+               public static TSource ElementAt<TSource> (      this ParallelQuery<TSource> source, int index)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (index < 0)
+                               throw new ArgumentOutOfRangeException ("index");
+                       if (index == 0) {
+                               try {
+                                       return source.First ();
+                               } catch (InvalidOperationException) {
+                                       throw new ArgumentOutOfRangeException ("index");
+                               }
+                       }
+
+                       TSource result = default (TSource);
+
+                       ParallelQuery<TSource> innerQuery = source.Where ((e, i) => i == index);
+
+                       try {
+                               result = innerQuery.First ();
+                       } catch (InvalidOperationException) {
+                               throw new ArgumentOutOfRangeException ("index");
+                       }
+
+                       return result;
+               }
+
+               public static TSource ElementAtOrDefault<TSource> (this ParallelQuery<TSource> source, int index)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       try {
+                               return source.ElementAt (index);
+                       } catch (ArgumentOutOfRangeException) {
+                               return default (TSource);
+                       }
+               }
+               #endregion
+
+               #region Intersect
+               public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
+                                                                        ParallelQuery<TSource> second)
+               {
+                       return Intersect<TSource> (first, second, EqualityComparer<TSource>.Default);
+               }
+
+               public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
+                                                                        ParallelQuery<TSource> second,
+                                                                        IEqualityComparer<TSource> comparer)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Intersect, comparer, first.Node, second.Node));
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
+                                                                        IEnumerable<TSource> second,
+                                                                        IEqualityComparer<TSource> comparer)
+               {
+                       throw new NotSupportedException ();
+               }
+               #endregion
+
+               #region Join
+               public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (      this ParallelQuery<TOuter> outer,
+                                                                                         ParallelQuery<TInner> inner,
+                                                                                         Func<TOuter, TKey> outerKeySelector,
+                                                                                         Func<TInner, TKey> innerKeySelector,
+                                                                                         Func<TOuter, TInner, TResult> resultSelector)
+               {
+                       return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
+               }
+               
+               public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (      this ParallelQuery<TOuter> outer,
+                                                                                         ParallelQuery<TInner> inner,
+                                                                                         Func<TOuter, TKey> outerKeySelector,
+                                                                                         Func<TInner, TKey> innerKeySelector,
+                                                                                         Func<TOuter, TInner, TResult> resultSelector,
+                                                                                         IEqualityComparer<TKey> comparer)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (      this ParallelQuery<TOuter> outer,
+                                                                                         IEnumerable<TInner> inner,
+                                                                                         Func<TOuter, TKey> outerKeySelector,
+                                                                                         Func<TInner, TKey> innerKeySelector,
+                                                                                         Func<TOuter, TInner, TResult> resultSelector)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
+                                                                                         IEnumerable<TInner> inner,
+                                                                                         Func<TOuter, TKey> outerKeySelector,
+                                                                                         Func<TInner, TKey> innerKeySelector,
+                                                                                         Func<TOuter, TInner, TResult> resultSelector,
+                                                                                         IEqualityComparer<TKey> comparer)
+               {
+                       throw new NotSupportedException ();
+               }
+               #endregion
+
+               #region Except
+               public static ParallelQuery<TSource> Except<TSource> (  this ParallelQuery<TSource> first,
+                                                                     ParallelQuery<TSource> second)
+               {
+                       return Except<TSource> (first, second, EqualityComparer<TSource>.Default);
+               }
+
+               public static ParallelQuery<TSource> Except<TSource> (  this ParallelQuery<TSource> first,
+                                                                     ParallelQuery<TSource> second,
+                                                                     IEqualityComparer<TSource> comparer)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Except,
+                                                                                     comparer, first.Node, second.Node));
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
+                                                                     IEnumerable<TSource> second)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Except<TSource> (  this ParallelQuery<TSource> first,
+                                                                     IEnumerable<TSource> second,
+                                                                     IEqualityComparer<TSource> comparer)
+               {
+                       throw new NotSupportedException ();
+               }
+               #endregion
+
+               #region Distinct
+               public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source)
+               {
+                       return Distinct<TSource> (source, EqualityComparer<TSource>.Default);
+               }
+
+               public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source, IEqualityComparer<TSource> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Distinct, comparer,
+                                                                                     source.Node, null));
+               }
+               #endregion
+
+               #region Union
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
+                                                                    IEnumerable<TSource> second)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Union<TSource>(this ParallelQuery<TSource> first,
+                                                                   IEnumerable<TSource> second,
+                                                                   IEqualityComparer<TSource> comparer)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
+                                                                    ParallelQuery<TSource> second)
+               {
+                       return first.Union (second, EqualityComparer<TSource>.Default);
+               }
+
+               public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
+                                                                    ParallelQuery<TSource> second,
+                                                                    IEqualityComparer<TSource> comparer)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+
+                       return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Union, comparer, first.Node, second.Node));
+               }
+               #endregion
+
+               #region Take
+               // TODO : introduce some early break up here, use ImplementerToken
+               public static ParallelQuery<TSource> Take<TSource> (this ParallelQuery<TSource> source, int count)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Where ((e, i) => i < count);
+               }
+
+               public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
+                                                                        Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where ((e) => predicate (e));
+               }
+
+               public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
+                                                                        Func<TSource, int, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where ((e, i) => predicate (e, i));
+               }
+               #endregion
+
+               #region Skip
+               public static ParallelQuery<TSource> Skip<TSource> (this ParallelQuery<TSource> source, int count)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Where ((e, i) => i >= count);
+               }
+
+               public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
+                                                                        Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where ((e) => !predicate (e));
+               }
+
+               public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
+                                                                        Func<TSource, int, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where ((e, i) => !predicate (e, i));
+               }
+               #endregion
+
+               #region Single
+               static TSource SingleInternal<TSource> (this ParallelQuery<TSource> source, params TSource[] init)
+               {
+                       TSource result = default(TSource);
+                       bool hasValue = false;
+
+                       foreach (TSource element in source) {
+                               if (hasValue)
+                                       throw new InvalidOperationException ("The input sequence contains more than one element.");
+
+                               result = element;
+                               hasValue = true;
+                       }
+
+                       if (!hasValue && init.Length != 0) {
+                               result = init[0];
+                               hasValue = true;
+                       }
+
+                       if (!hasValue)
+                               throw new InvalidOperationException ("The input sequence is empty.");
+
+                       return result;
+               }
+
+               public static TSource Single<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return SingleInternal<TSource> (source);
+               }
+
+               public static TSource Single<TSource> (this ParallelQuery<TSource> source,
+                                                      Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where (predicate).Single ();
+               }
+
+               public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return SingleInternal<TSource> (source, default (TSource));
+               }
+
+               public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where (predicate).SingleOrDefault ();
+               }
+               #endregion
+
+               #region Count
+               public static int Count<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate<TSource, int, int> (() => 0,
+                                                                  (acc, e) => acc + 1,
+                                                                  (acc1, acc2) => acc1 + acc2,
+                                                                  (result) => result);
+               }
+
+               public static int Count<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where (predicate).Count ();
+               }
+
+               public static long LongCount<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate<TSource, long, long> (() => 0,
+                                                                     (acc, e) => acc + 1,
+                                                                     (acc1, acc2) => acc1 + acc2,
+                                                                     (result) => result);
+               }
+
+               public static long LongCount<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (predicate == null)
+                               throw new ArgumentNullException ("predicate");
+
+                       return source.Where (predicate).LongCount ();
+               }
+               #endregion
+
+               #region Average
+               public static double Average (this ParallelQuery<int> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (() => new int[2],
+                                               (acc, e) => { acc[0] += e; acc[1]++; return acc; },
+                                               (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
+                                               (acc) => acc[0] / ((double)acc[1]));
+               }
+
+               public static double Average (this ParallelQuery<long> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (() => new long[2],
+                                               (acc, e) => { acc[0] += e; acc[1]++; return acc; },
+                                               (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
+                                               (acc) => acc[0] / ((double)acc[1]));
+               }
+
+               public static decimal Average (this ParallelQuery<decimal> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (() => new decimal[2],
+                                               (acc, e) => { acc[0] += e; acc[1]++; return acc; },
+                                               (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
+                                               (acc) => acc[0] / acc[1]);
+               }
+
+               public static double Average (this ParallelQuery<double> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (() => new double[2],
+                                               (acc, e) => { acc[0] += e; acc[1]++; return acc; },
+                                               (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
+                                               (acc) => acc[0] / ((double)acc[1]));
+               }
+
+               public static float Average (this ParallelQuery<float> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (() => new float[2],
+                                               (acc, e) => { acc[0] += e; acc[1]++; return acc; },
+                                               (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
+                                               (acc) => acc[0] / acc[1]);
+               }
+               #endregion
+
+               #region More Average
+               public static double? Average (this ParallelQuery<int?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();;
+               }
+
+               public static double? Average (this ParallelQuery<long?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
+               }
+
+               public static decimal? Average (this ParallelQuery<decimal?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
+               }
+
+               public static double? Average (this ParallelQuery<double?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
+               }
+
+               public static float? Average (this ParallelQuery<float?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
+               }
+
+               public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static float Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static decimal Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static float? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+
+               public static decimal? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Average ();
+               }
+               #endregion
+
+               #region Sum
+               public static int Sum (ParallelQuery<int> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
+               }
+
+               public static long Sum (ParallelQuery<long> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate ((long)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
+               }
+
+               public static float Sum (ParallelQuery<float> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (0.0f, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
+               }
+
+               public static double Sum (ParallelQuery<double> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate (0.0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
+               }
+
+               public static decimal Sum (ParallelQuery<decimal> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Aggregate ((decimal)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
+               }
+
+               public static int? Sum (ParallelQuery<int?> source)
+               {
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
+               }
+
+               public static long? Sum (ParallelQuery<long?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
+               }
+
+               public static float? Sum (ParallelQuery<float?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
+               }
+
+               public static double? Sum (ParallelQuery<double?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
+               }
+
+               public static decimal? Sum (ParallelQuery<decimal?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
+               }
+
+               public static int Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, int> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static long Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, long> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static decimal Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, decimal> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static float Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, float> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static double Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, double> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static int? Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, int?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static long? Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, long?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static decimal? Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, decimal?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static float? Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, float?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+
+               public static double? Sum<TSource> (ParallelQuery<TSource> source, Func<TSource, double?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Sum ();
+               }
+               #endregion
+
+               #region Min-Max
+               static T BestOrder<T> (ParallelQuery<T> source, Func<T, T, bool> bestSelector, T seed)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       T best = seed;
+
+                       best = source.Aggregate (() => seed,
+                                               (first, second) => (bestSelector(first, second)) ? first : second,
+                                               (first, second) => (bestSelector(first, second)) ? first : second,
+                                               (e) => e);
+                       return best;
+               }
+
+               public static int Min (this ParallelQuery<int> source)
+               {
+                       return BestOrder (source, (first, second) => first < second, int.MaxValue);
+               }
+
+               public static long Min (this ParallelQuery<long> source)
+               {
+                       return BestOrder (source, (first, second) => first < second, long.MaxValue);
+               }
+
+               public static float Min (this ParallelQuery<float> source)
+               {
+                       return BestOrder (source, (first, second) => first < second, float.MaxValue);
+               }
+
+               public static double Min (this ParallelQuery<double> source)
+               {
+                       return BestOrder (source, (first, second) => first < second, double.MaxValue);
+               }
+
+               public static decimal Min (this ParallelQuery<decimal> source)
+               {
+                       return BestOrder (source, (first, second) => first < second, decimal.MaxValue);
+               }
+
+               public static TSource Min<TSource> (this ParallelQuery<TSource> source)
+               {
+                       IComparer<TSource> comparer = Comparer<TSource>.Default;
+
+                       return BestOrder (source, (first, second) => comparer.Compare (first, second) < 0, default (TSource));
+               }
+
+               public static TResult Min<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static int? Min (this ParallelQuery<int?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : int.MaxValue).Min ();
+               }
+
+               public static long? Min (this ParallelQuery<long?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : long.MaxValue).Min ();
+               }
+
+               public static float? Min (this ParallelQuery<float?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : float.MaxValue).Min ();
+               }
+
+               public static double? Min (this ParallelQuery<double?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : double.MaxValue).Min ();
+               }
+
+               public static decimal? Min (this ParallelQuery<decimal?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : decimal.MaxValue).Min ();
+               }
+
+               public static int Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static long Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static float Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static double Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static decimal Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static int? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static long? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static float? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static double? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static decimal? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Min ();
+               }
+
+               public static int Max (this ParallelQuery<int> source)
+               {
+                       return BestOrder (source, (first, second) => first > second, int.MinValue);
+               }
+
+               public static long Max(this ParallelQuery<long> source)
+               {
+                       return BestOrder(source, (first, second) => first > second, long.MinValue);
+               }
+
+               public static float Max (this ParallelQuery<float> source)
+               {
+                       return BestOrder(source, (first, second) => first > second, float.MinValue);
+               }
+
+               public static double Max (this ParallelQuery<double> source)
+               {
+                       return BestOrder(source, (first, second) => first > second, double.MinValue);
+               }
+
+               public static decimal Max (this ParallelQuery<decimal> source)
+               {
+                       return BestOrder(source, (first, second) => first > second, decimal.MinValue);
+               }
+
+               public static TSource Max<TSource> (this ParallelQuery<TSource> source)
+               {
+                       IComparer<TSource> comparer = Comparer<TSource>.Default;
+
+                       return BestOrder (source, (first, second) => comparer.Compare (first, second) > 0, default (TSource));
+               }
+
+               public static TResult Max<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static int? Max (this ParallelQuery<int?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : int.MinValue).Max ();
+               }
+
+               public static long? Max (this ParallelQuery<long?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : long.MinValue).Max ();
+               }
+
+               public static float? Max (this ParallelQuery<float?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : float.MinValue).Max ();
+               }
+
+               public static double? Max (this ParallelQuery<double?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : double.MinValue).Max ();
+               }
+
+               public static decimal? Max (this ParallelQuery<decimal?> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.Select ((e) => e.HasValue ? e.Value : decimal.MinValue).Max ();
+               }
+
+               public static int Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static long Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static float Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static double Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static decimal Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static int? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static long? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static float? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static double? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+
+               public static decimal? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (func == null)
+                               throw new ArgumentNullException ("func");
+
+                       return source.Select (func).Max ();
+               }
+               #endregion
+
+               #region Cast / OfType
+               public static ParallelQuery<TResult> Cast<TResult> (this ParallelQuery source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.TypedQuery.Select ((e) => (TResult)e);
+               }
+
+               public static ParallelQuery<TResult> OfType<TResult> (ParallelQuery source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return source.TypedQuery.Where ((e) => e is TResult).Cast<TResult> ();
+               }
+               #endregion
+
+               #region Reverse
+               public static ParallelQuery<TSource> Reverse<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       return new ParallelQuery<TSource> (new QueryReverseNode<TSource> (source));
+               }
+               #endregion
+
+               #region ToArray - ToList - ToDictionary - ToLookup
+               public static List<TSource> ToList<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       OrderedParallelQuery<TSource> ordered = null;
+                       if ((ordered = source as OrderedParallelQuery<TSource>) != null)
+                               return ToListOrdered (ordered);
+
+                       List<TSource> temp = source.Aggregate (() => new List<TSource>(50),
+                                                              (list, e) => { list.Add (e); return list; },
+                                                              (list, list2) => { list.AddRange (list2); return list; },
+                                                              (list) => list);
+                       return temp;
+               }
+
+               static List<TSource> ToListOrdered<TSource> (this OrderedParallelQuery<TSource> source)
+               {
+                       List<TSource> result = new List<TSource> ();
+
+                       foreach (TSource element in source)
+                               result.Add (element);
+
+                       return result;
+               }
+
+               public static TSource[] ToArray<TSource> (this ParallelQuery<TSource> source)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+
+                       TSource[] result = null;
+
+                       Func<List<TSource>, TSource, List<TSource>> intermediate = (list, e) => {
+                               list.Add (e); return list;
+                       };
+
+                       Action<IList<List<TSource>>> final = (list) => {
+                               int count = 0;
+
+                               for (int i = 0; i < list.Count; i++)
+                                 count += list[i].Count;
+
+                               result = new TSource[count];
+                               int insertIndex = -1;
+
+                               for (int i = 0; i < list.Count; i++)
+                                 for (int j = 0; j < list[i].Count; j++)
+                                   result [++insertIndex] = list[i][j];
+                       };
+
+                       ParallelExecuter.ProcessAndAggregate<TSource, List<TSource>> (source.Node,
+                                                                                     () => new List<TSource> (),
+                                                                                     intermediate,
+                                                                                     final);
+
+                       return result;
+               }
+
+               public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                    Func<TSource, TKey> keySelector,
+                                                                                    IEqualityComparer<TKey> comparer)
+               {
+                       return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
+               }
+
+               public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
+                                                                                    Func<TSource, TKey> keySelector)
+               {
+                       return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
+               }
+
+               public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                                 Func<TSource, TKey> keySelector,
+                                                                                                 Func<TSource, TElement> elementSelector)
+               {
+                       return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
+               }
+
+               public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                                 Func<TSource, TKey> keySelector,
+                                                                                                 Func<TSource, TElement> elementSelector,
+                                                                                                 IEqualityComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+                       if (elementSelector == null)
+                               throw new ArgumentNullException ("elementSelector");
+
+                       return source.Aggregate (() => new Dictionary<TKey, TElement> (comparer),
+                                                 (d, e) => { d.Add (keySelector (e), elementSelector (e)); return d; },
+                                                 (d1, d2) => { foreach (var couple in d2) d1.Add (couple.Key, couple.Value); return d1; },
+                                                 (d) => d);
+               }
+
+               public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (  this ParallelQuery<TSource> source,
+                                                                             Func<TSource, TKey> keySelector)
+               {
+                       return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
+               }
+
+               public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (  this ParallelQuery<TSource> source,
+                                                                             Func<TSource, TKey> keySelector,
+                                                                             IEqualityComparer<TKey> comparer)
+               {
+                       return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
+               }
+
+               public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                        Func<TSource, TKey> keySelector,
+                                                                                        Func<TSource, TElement> elementSelector)
+               {
+                       return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
+               }
+
+               public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
+                                                                                        Func<TSource, TKey> keySelector,
+                                                                                        Func<TSource, TElement> elementSelector,
+                                                                                        IEqualityComparer<TKey> comparer)
+               {
+                       if (source == null)
+                               throw new ArgumentNullException ("source");
+                       if (keySelector == null)
+                               throw new ArgumentNullException ("keySelector");
+                       if (comparer == null)
+                               throw new ArgumentNullException ("comparer");
+                       if (elementSelector == null)
+                               throw new ArgumentNullException ("elementSelector");
+
+                       ConcurrentLookup<TKey, TElement> lookup = new ConcurrentLookup<TKey, TElement> (comparer);
+                       source.ForAll ((e) => lookup.Add (keySelector (e), elementSelector (e)));
+
+                       return lookup;
+               }
+               #endregion
+
+               #region Concat
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than "
+                                  + "System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method "
+                                  + "to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TSource> Concat<TSource>(this ParallelQuery<TSource> first,
+                                                                    IEnumerable<TSource> second)
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public static ParallelQuery<TSource> Concat<TSource> (  this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
+               {
+                       return new ParallelQuery<TSource> (new QueryConcatNode<TSource> (first.Node, second.Node));
+               }
+               #endregion
+               
+               #region DefaultIfEmpty
+               public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (  this ParallelQuery<TSource> source)
+               {
+                       return source.DefaultIfEmpty (default (TSource));
+               }
+               
+               public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (  this ParallelQuery<TSource> source, TSource defaultValue)
+               {
+                       return new ParallelQuery<TSource> (new QueryDefaultEmptyNode<TSource> (source.Node, defaultValue));
+               }
+               #endregion
+               
+               #region First
+               public static TSource First<TSource> (  this ParallelQuery<TSource> source)
+               {
+                       CancellationTokenSource src = new CancellationTokenSource ();
+                       IEnumerator<TSource> enumerator = source.WithImplementerToken (src).GetEnumerator ();
+                       
+                       if (enumerator == null || !enumerator.MoveNext ())
+                               throw new InvalidOperationException ("source contains no element");
+                       
+                       TSource result = enumerator.Current;
+                       src.Cancel ();
+                       
+                       return result;
+               }
+               
+               public static TSource First<TSource> (  this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       return source.Where (predicate).First ();
+               }
+               
+               public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source)
+               {
+                       return source.DefaultIfEmpty ().First ();
+               }
+               
+               public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       return source.Where (predicate).FirstOrDefault ();
+               }
+               #endregion
+               
+               #region Last
+               public static TSource Last<TSource> (this ParallelQuery<TSource> source)
+               {
+                       return source.Reverse ().First ();
+               }
+               
+               public static TSource Last<TSource> (   this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       return source.Reverse ().First (predicate);
+               }
+               
+               public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source)
+               {
+                       return source.Reverse ().FirstOrDefault ();
+               }
+               
+               public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
+               {
+                       return source.Reverse ().FirstOrDefault (predicate);
+               }
+               #endregion
+
+               #region Zip
+               public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
+                                                                                     ParallelQuery<TSecond> second,
+                                                                                     Func<TFirst, TSecond, TResult> resultSelector)
+               {
+                       if (first == null)
+                               throw new ArgumentNullException ("first");
+                       if (second == null)
+                               throw new ArgumentNullException ("second");
+                       if (resultSelector == null)
+                               throw new ArgumentNullException ("resultSelector");
+
+                       return new ParallelQuery<TResult> (new QueryZipNode<TFirst, TSecond, TResult> (resultSelector, first.Node, second.Node));
+               }
+
+               [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
+                                  + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
+                                  + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
+               public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
+                                                                                     IEnumerable<TSecond> second,
+                                                                                     Func<TFirst, TSecond, TResult> resultSelector)
+               {
+                       throw new NotSupportedException ();
+               }
+               #endregion
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/ParallelExecuter.cs b/mcs/class/System.Core/System.Linq/ParallelExecuter.cs
new file mode 100644 (file)
index 0000000..24f9c1a
--- /dev/null
@@ -0,0 +1,193 @@
+#if NET_4_0
+//
+// ParallelExecuter.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+namespace System.Linq
+{
+       // TODO: Refactory each of the Process method into one big entity
+       // Check CancellationToken.Canceled parameter in the Task's action body too
+       internal static class ParallelExecuter
+       {
+               internal static QueryOptions CheckQuery<T> (QueryBaseNode<T> startingNode)
+               {
+                       return CheckQuery<T> (startingNode, false);
+               }
+
+               internal static QueryOptions CheckQuery<T> (QueryBaseNode<T> startingNode, bool blocking)
+               {
+                       return CheckQuery (startingNode, GetBestWorkerNumber (blocking));
+               }
+
+               internal static QueryOptions CheckQuery<T> (QueryBaseNode<T> startingNode, int partitionCount)
+               {
+                       QueryCheckerVisitor visitor = new QueryCheckerVisitor (partitionCount);
+                       startingNode.Visit (visitor);
+
+                       return visitor.Options;
+               }
+
+               // QueryOptions.ImplementerToken = QueryOptions.ImplementerToken.Chain (myOperatorSource);
+               internal static CancellationToken Chain (this CancellationToken self, CancellationTokenSource other)
+               {
+                       CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource (self, other.Token);
+                       return linked.Token;
+               }
+
+               internal static int GetBestWorkerNumber ()
+               {
+                       return GetBestWorkerNumber (false);
+               }
+
+               internal static int GetBestWorkerNumber (bool blocking)
+               {
+                       return blocking ? Environment.ProcessorCount + 1 : Environment.ProcessorCount;
+               }
+
+               internal static Task[] Process<TSource, TElement> (QueryBaseNode<TSource> node, Action<TElement> call,
+                                                                  Func<QueryBaseNode<TSource>, QueryOptions, IList<IEnumerable<TElement>>> acquisitionFunc,
+                                                                  QueryOptions options)
+               {
+                       return Process<TSource, TElement> (node, call, acquisitionFunc, null, options);
+               }
+
+               internal static Task[] Process<TSource, TElement> (QueryBaseNode<TSource> node, Action<TElement> call,
+                                                                  Func<QueryBaseNode<TSource>, QueryOptions, IList<IEnumerable<TElement>>> acquisitionFunc,
+                                                                  Action endAction,
+                                                                  QueryOptions options)
+               {
+                       IList<IEnumerable<TElement>> enumerables = acquisitionFunc (node, options);
+
+                       Task[] tasks = new Task[enumerables.Count];
+
+                       for (int i = 0; i < tasks.Length; i++) {
+                               int index = i;
+                               tasks[i] = Task.Factory.StartNew (() => {
+                                       foreach (TElement item in enumerables[index]) {
+                                               // This is from specific operators
+                                               if (options.ImplementerToken.IsCancellationRequested)
+                                                       break;
+                                               if (options.Token.IsCancellationRequested)
+                                                       throw new OperationCanceledException (options.Token);
+
+                                               call (item);
+                                       }
+                                       if (endAction != null)
+                                               endAction ();
+                                 }, options.Token);
+                       }
+
+                       return tasks;
+               }
+
+               internal static void ProcessAndBlock<T> (QueryBaseNode<T> node, Action<T> call)
+               {
+                       QueryOptions options = CheckQuery (node, true);
+
+                       Task[] tasks = Process (node, call, (n, o) => n.GetEnumerables (o), options);
+                       Task.WaitAll (tasks, options.Token);
+               }
+
+               internal static Action ProcessAndCallback<T> (QueryBaseNode<T> node, Action<T> call,
+                                                             Action callback, QueryOptions options)
+               {
+                       Task[] tasks = Process (node, call, (n, o) => n.GetEnumerables (o), options);
+                       Task.Factory.ContinueWhenAll (tasks,  (_) => callback ());
+
+                       return () => Task.WaitAll (tasks, options.Token);
+               }
+
+               internal static Action ProcessAndCallback<T> (QueryBaseNode<T> node, Action<KeyValuePair<long, T>> call,
+                                                             Action callback, QueryOptions options)
+               {
+                       return ProcessAndCallback<T> (node, call, null, callback, options);
+               }
+
+               internal static Action ProcessAndCallback<T> (QueryBaseNode<T> node, Action<KeyValuePair<long, T>> call,
+                                                             Action endAction,
+                                                             Action callback, QueryOptions options)
+               {
+                       Task[] tasks = Process (node, call, (n, o) => n.GetOrderedEnumerables (o), endAction, options);
+                       Task.Factory.ContinueWhenAll (tasks,  (_) => callback ());
+
+                       return () => Task.WaitAll (tasks, options.Token);
+               }
+
+               internal static void ProcessAndAggregate<T, U> (QueryBaseNode<T> node,
+                                                   Func<U> seedFunc,
+                                                   Func<U, T, U> localCall,
+                                                   Action<IList<U>> call)
+               {
+                       QueryOptions options = CheckQuery (node, true);
+
+                       IList<IEnumerable<T>> enumerables = node.GetEnumerables (options);
+                       U[] locals = new U[enumerables.Count];
+                       Task[] tasks = new Task[enumerables.Count];
+
+                       bool init = false;
+                       if (seedFunc != null) {
+                               for (int i = 0; i < locals.Length; i++)
+                                       locals[i] = seedFunc ();
+                               init = true;
+                       }
+
+                       for (int i = 0; i < tasks.Length; i++) {
+                               int index = i;
+                               tasks[i] = Task.Factory.StartNew (() => {
+                                       foreach (T item in enumerables[index]) {
+                                               // This is from specific operators
+                                               if (options.ImplementerToken.IsCancellationRequested)
+                                                       break;
+                                               if (options.Token.IsCancellationRequested)
+                                                       throw new OperationCanceledException (options.Token);
+
+                                               if (!init) {
+                                                       init = true;
+                                                       // HACK: TODO: omfwtfitsomuchsucks
+                                                       locals[index] = (U)(object)item;
+                                                       continue;
+                                               }
+                                               
+                                               U acc = locals[index];
+                                               locals[index] = localCall (acc, item);
+                                       }
+                               }, options.Token);
+                       }
+
+                       Task.WaitAll (tasks, options.Token);
+
+                       if (call != null)
+                               call (locals);
+               }
+       }
+}
+#endif
\ No newline at end of file
diff --git a/mcs/class/System.Core/System.Linq/ParallelPartitioner.cs b/mcs/class/System.Core/System.Linq/ParallelPartitioner.cs
new file mode 100644 (file)
index 0000000..50d6235
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// ParallelPartitioner.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+#if NET_4_0
+
+namespace System.Linq
+{
+       internal static class ParallelPartitioner
+       {
+               internal static OrderablePartitioner<T> CreateForChunks<T> (IEnumerable<T> source)
+               {
+                       return Partitioner.Create (source);
+               }
+
+               internal static OrderablePartitioner<T> CreateForRange<T> (IList<T> source)
+               {
+                       return Partitioner.Create (source, true);
+               }
+
+               internal static OrderablePartitioner<T> CreateBest<T> (IEnumerable<T> source)
+               {
+                       IList<T> temp = source as IList<T>;
+                       if (temp != null)
+                               return CreateForRange (temp);
+
+                       return CreateForChunks (source);
+               }
+
+               internal static OrderablePartitioner<T> CreateForStrips<T> (IEnumerable<T> source, int stripSize)
+               {
+                       IList<T> temp = source as IList<T>;
+                       if (temp != null)
+                               return new StripPartitioner<T> (temp);
+
+                       return new EnumerablePartitioner<T> (source, stripSize, 1);
+               }
+
+               internal static OrderablePartitioner<int> CreateForRange (int start, int count)
+               {
+                       return CreateForRange<int> (new RangeList (start, count));
+               }
+
+               internal static OrderablePartitioner<T> CreateForRepeat<T> (T obj, int count)
+               {
+                       return CreateForRange<T> (new RepeatList<T> (obj, count));
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/ParallelQuery.cs b/mcs/class/System.Core/System.Linq/ParallelQuery.cs
new file mode 100644 (file)
index 0000000..6d99813
--- /dev/null
@@ -0,0 +1,125 @@
+//
+// ParallelQuery.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+#if NET_4_0
+
+namespace System.Linq
+{
+       public class ParallelQuery : IEnumerable
+       {
+               ParallelExecutionMode execMode = ParallelExecutionMode.Default;
+               ParallelMergeOptions mergeOptions = ParallelMergeOptions.Default;
+
+               internal ParallelQuery ()
+               {
+
+               }
+
+               internal ParallelMergeOptions MergeOptions {
+                       get {
+                               return mergeOptions;
+                       }
+                       set {
+                               mergeOptions = value;
+                       }
+               }
+
+               internal ParallelExecutionMode ExecMode {
+                       get {
+                               return execMode;
+                       }
+                       set {
+                               execMode = value;
+                       }
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return GetEnumeratorTrick ();
+               }
+
+               // Trick to get the correct IEnumerator from ParallelQuery<TSource>
+               internal virtual IEnumerator GetEnumeratorTrick ()
+               {
+                       return null;
+               }
+               
+               internal virtual ParallelQuery<object> TypedQuery {
+                       get {
+                               return null;
+                       }
+               }
+       }
+
+       public class ParallelQuery<TSource> : ParallelQuery, IEnumerable<TSource>, IEnumerable
+       {
+               QueryBaseNode<TSource> node;
+
+               internal ParallelQuery (QueryBaseNode<TSource> node)
+               {
+                       this.node = node;
+               }
+
+               internal QueryBaseNode<TSource> Node {
+                       get {
+                               return node;
+                       }
+               }
+
+               public virtual IEnumerator<TSource> GetEnumerator ()
+               {
+                       return GetEnumeratorInternal ();
+               }
+
+               IEnumerator IEnumerable.GetEnumerator ()
+               {
+                       return (IEnumerator)GetEnumeratorInternal ();
+               }
+
+               IEnumerator<TSource> GetEnumeratorInternal ()
+               {
+                       return new ParallelQueryEnumerator<TSource> (node);
+               }
+
+               internal override IEnumerator GetEnumeratorTrick ()
+               {
+                       return (IEnumerator)GetEnumeratorInternal ();
+               }
+               
+               internal override ParallelQuery<object> TypedQuery {
+                       get {
+                               return new ParallelQuery<object> (new QueryCastNode<TSource> (node));
+                       }
+               }
+       }
+}
+#endif
diff --git a/mcs/class/System.Core/System.Linq/ParallelQueryEnumerator.cs b/mcs/class/System.Core/System.Linq/ParallelQueryEnumerator.cs
new file mode 100644 (file)
index 0000000..d40d20e
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// ParallelEnumerator.cs
+//
+// Author:
+//       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
+//
+// Copyright (c) 2010 Jérémie "Garuma" Laval
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+using System;
+using System.Threading;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Concurrent;
+
+#if NET_4_0
+
+namespace System.Linq
+{
+       internal class ParallelQueryEnumerator<T> : IEnumerator<T>
+       {
+               readonly int DefaultBufferSize = ParallelExecuter.GetBestWorkerNumber () * 50;
+
+               BlockingCollection<T> buffer;
+               IEnumerator<T> loader;
+               QueryOptions options;
+               OrderingEnumerator<T> ordEnumerator;
+
+               T current;
+
+               Action waitAction;
+
+               internal ParallelQueryEnumerator (QueryBaseNode<T> node)
+               {
+                       this.options = ParallelExecuter.CheckQuery (node);
+                       Setup ();
+
+                       // Launch adding to the buffer asynchronously via Tasks
+                       if (options.BehindOrderGuard.Value) {
+                               // Keep fairness between tasks (i.e. the same task don't ruin order by adding to much of its own)
+                               Barrier barrier = new Barrier (options.PartitionCount);
+                               waitAction = ParallelExecuter.ProcessAndCallback (node,
+                                                                                 (e) => { ordEnumerator.KeyedBuffer.Add (e); barrier.SignalAndWait (); },
+                                                                                 barrier.RemoveParticipant,
+                                                                                 ordEnumerator.KeyedBuffer.CompleteAdding,
+                                                                                 options);
+                       } else {
+                               waitAction = ParallelExecuter.ProcessAndCallback (node,
+                                                                                 buffer.Add,
+                                                                                 buffer.CompleteAdding,
+                                                                                 options);
+                       }
+
+                       if (options.Options.HasValue && options.Options.Value == ParallelMergeOptions.FullyBuffered)
+                               waitAction ();
+               }
+
+               void Setup ()
+               {
+                       if (!options.BehindOrderGuard.Value) {
+                               if (options.Options.HasValue && (options.Options.Value == ParallelMergeOptions.NotBuffered
+                                                                || options.Options.Value == ParallelMergeOptions.FullyBuffered)) {
+                                       buffer = new BlockingCollection<T> ();
+                               } else {
+                                       buffer = new BlockingCollection<T> (DefaultBufferSize);
+                               }
+
+                               IEnumerable<T> source = buffer.GetConsumingEnumerable (options.Token);
+
+                               loader = source.GetEnumerator ();
+                       } else {
+                               loader = ordEnumerator = new OrderingEnumerator<T> (options.PartitionCount);
+                       }
+               }
+
+               public void Dispose ()
+               {
+
+               }
+
+               public void Reset ()
+               {
+                       throw new NotSupportedException ();
+               }
+
+               public bool MoveNext ()
+               {
+                       // If there are no stuff in the buffer
+                       // but CompleteAdding hasn't been called,
+                       // MoveNext blocks until further results are produced
+                       if (!loader.MoveNext ())
+                               return false;
+
+                       current = loader.Current;
+                       return true;
+               }
+
+               public T Current {
+                       get {
+                               return current;
+                       }
+               }
+
+               object IEnumerator.Current {
+                       get {
+                               return current;
+                       }
+               }
+       }
+}
+#endif
index a44537e0ab20ed2e92bc6a0630856f7b4d0bea40..220ab49fbca08b40211efa83e6a5e2adee86fd31 100644 (file)
@@ -209,3 +209,48 @@ System.IO/HandleInheritability.cs
 ../dlr/Runtime/Microsoft.Scripting.Core/Utils/ReferenceEqualityComparer.cs
 ../dlr/Runtime/Microsoft.Scripting.Core/Utils/TrueReadOnlyCollection.cs
 ../dlr/Runtime/Microsoft.Scripting.Core/Utils/TypeExtensions.cs
+System.Linq/ParallelQueryEnumerator.cs
+System.Linq/OrderedParallelQuery.cs
+System.Linq/ParallelMergeOptions.cs
+System.Linq/ParallelExecutionMode.cs
+System.Linq/ParallelEnumerable.cs
+System.Linq/ParallelPartitioner.cs
+System.Linq/Internal/RangeList.cs
+System.Linq/Internal/StripPartitioner.cs
+System.Linq/Internal/RepeatList.cs
+System.Linq/Internal/ParallelQuickSort.cs
+System.Linq/Internal/OrderingEnumerator.cs
+System.Linq/Internal/AggregationList.cs
+System.Linq/Internal/ConcurrentLookup.cs
+System.Linq/Internal/ConcurrentGrouping.cs
+System.Linq/Internal/ReverseList.cs
+System.Linq/ParallelExecuter.cs
+System.Linq/ParallelQuery.cs
+System.Linq/Internal/QueryNodes/QueryWhereNode.cs
+System.Linq/Internal/QueryNodes/QueryCastNode.cs
+System.Linq/Internal/QueryNodes/QueryConcatNode.cs
+System.Linq/Internal/QueryNodes/QueryDefaultEmptyNode.cs
+System.Linq/Internal/QueryNodes/QueryOptionNode.cs
+System.Linq/Internal/QueryNodes/QueryGroupByNode.cs
+System.Linq/Internal/QueryNodes/QuerySelectNode.cs
+System.Linq/Internal/QueryNodes/QuerySelectManyNode.cs
+System.Linq/Internal/QueryNodes/QueryStreamNode.cs
+System.Linq/Internal/QueryNodes/QueryOrderedStreamNode.cs
+System.Linq/Internal/QueryNodes/QueryStartNode.cs
+System.Linq/Internal/QueryNodes/QueryBaseNode.cs
+System.Linq/Internal/QueryNodes/QueryChildNode.cs
+System.Linq/Internal/QueryNodes/QueryOrderGuardNode.cs
+System.Linq/Internal/QueryNodes/QueryOrderByNode.cs
+System.Linq/Internal/QueryNodes/QueryMuxNode.cs
+System.Linq/Internal/QueryNodes/QueryZipNode.cs
+System.Linq/Internal/QueryNodes/QuerySetNode.cs
+System.Linq/Internal/QueryNodes/QueryReverseNode.cs
+System.Linq/Internal/QueryNodes/SetInclusion.cs
+System.Linq/Internal/Visitors/INodeVisitor.cs
+System.Linq/Internal/Visitors/IVisitableNode.cs
+System.Linq/Internal/Visitors/QueryCheckerVisitor.cs
+System.Linq/Internal/Visitors/QueryOptions.cs
+System.Linq/Internal/QueryNodes/WrapHelper.cs
+../corlib/System.Collections.Concurrent/Partitioners/EnumerablePartitioner.cs
+../corlib/System.Collections.Concurrent/ConcurrentSkipList.cs
+