+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.
+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:
--- /dev/null
+#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
--- /dev/null
+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
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
+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)
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+2010-04-15 Jérémie Laval <jeremie.laval@gmail.com>
+
+ * INodeVisitor.cs:
+ * IVisitableNode.cs:
+ * QueryCheckerVisitor.cs:
+ * QueryOptions.cs: First check-in of PLinq
+
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
--- /dev/null
+//
+// 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
../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
+