Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Implement ordered enumerable enumerators via Iterator.
  • Loading branch information
JonHanna authored and benaadams committed May 19, 2016
commit a9fbca7464165477a3179dc6740fb4e23cae2639
2 changes: 1 addition & 1 deletion src/System.Linq/src/System/Linq/Iterator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static partial class Enumerable
{
internal abstract class Iterator<TSource> : IEnumerable<TSource>, IEnumerator<TSource>
{
private readonly int _threadId;
protected readonly int _threadId;
internal int _state;
internal TSource _current;

Expand Down
214 changes: 80 additions & 134 deletions src/System.Linq/src/System/Linq/OrderedEnumerable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,66 +9,80 @@

namespace System.Linq
{
internal abstract class OrderedEnumerable<TElement> : IOrderedEnumerable<TElement>, IPartition<TElement>
internal abstract class OrderedEnumerable<TElement> : Enumerable.Iterator<TElement>, IOrderedEnumerable<TElement>, IPartition<TElement>
{
private const int ArrayPoolUseThreshold = 32;
internal IEnumerable<TElement> _source;
private Buffer<TElement> _buffer;
private int _index;
private int _maxIdx = int.MaxValue;
private int[] _map;

private int[] SortedMap(Buffer<TElement> buffer)
private int[] SortedMap(Buffer<TElement> buffer, bool rent)
{
return GetEnumerableSorter().Sort(buffer._items, buffer._count);
return GetEnumerableSorter().Sort(buffer._items, buffer._count, rent);
}

private int[] SortedMap(Buffer<TElement> buffer, int minIdx, int maxIdx)
private int[] SortedMap(Buffer<TElement> buffer, int minIdx, int maxIdx, bool rent)
{
return GetEnumerableSorter().Sort(buffer._items, buffer._count, minIdx, maxIdx);
return GetEnumerableSorter().Sort(buffer._items, buffer._count, minIdx, maxIdx, rent);
}

public IEnumerator<TElement> GetEnumerator()
public override bool MoveNext()
{
Buffer<TElement> buffer = new Buffer<TElement>(_source);
if (buffer._count >= 32)
{
return GetLargeEnumerator(buffer);
}
else if (buffer._count > 0)
switch (_state)
{
return GetSmallEnumerator(buffer);
}

return GetEmptyEnumerator();
}

private IEnumerator<TElement> GetEmptyEnumerator()
{
yield break;
}
case 1:
Buffer<TElement> buffer = new Buffer<TElement>(_source);
if (buffer._count > 0)
{
if (_index != 0 || _maxIdx != int.MaxValue)
{
_map = SortedMap(buffer, _index, _maxIdx, buffer._count >= ArrayPoolUseThreshold);
}
else
{
_map = SortedMap(buffer, buffer._count >= ArrayPoolUseThreshold);
}

_maxIdx = Math.Min(_maxIdx, buffer._count - 1);
_buffer = buffer;
_state = 2;
goto case 2;
}

private IEnumerator<TElement> GetSmallEnumerator(Buffer<TElement> buffer)
{
int[] map = SortedMap(buffer);
for (int i = 0; i < buffer._count; i++)
{
yield return buffer._items[map[i]];
break;
case 2:
if (_index <= _maxIdx)
{
_current = _buffer._items[_map[_index]];
++_index;
return true;
}
break;
}

Dispose();
return false;
}

private IEnumerator<TElement> GetLargeEnumerator(Buffer<TElement> buffer)
public override void Dispose()
{
int[] map = null;
try
base.Dispose();
if (_map != null)
{
map = SortedMap(buffer);
for (int i = 0; i < buffer._count; i++)
_buffer = default(Buffer<TElement>);
if (_map.Length >= ArrayPoolUseThreshold)
{
yield return buffer._items[map[i]];
int[] rented = Interlocked.Exchange(ref _map, null);
if (rented != null)
{
ArrayPool<int>.Shared.Return(rented);
}
}
}
finally
{
var rentedMap = Interlocked.Exchange(ref map, null);
if (rentedMap != null)
else
{
ArrayPool<int>.Shared.Return(rentedMap);
_map = null;
}
}
}
Expand All @@ -84,17 +98,13 @@ public TElement[] ToArray()
}

TElement[] array = new TElement[count];
int[] map = SortedMap(buffer);
int[] map = SortedMap(buffer, true);
for (int i = 0; i != array.Length; i++)
{
array[i] = buffer._items[map[i]];
}

if (count >= 32)
{
ArrayPool<int>.Shared.Return(map);
}

ArrayPool<int>.Shared.Return(map);
return array;
}

Expand All @@ -105,16 +115,13 @@ public List<TElement> ToList()
List<TElement> list = new List<TElement>(count);
if (count > 0)
{
int[] map = SortedMap(buffer);
int[] map = SortedMap(buffer, true);
for (int i = 0; i != count; i++)
{
list.Add(buffer._items[map[i]]);
}

if (count >= 32)
{
ArrayPool<int>.Shared.Return(map);
}
ArrayPool<int>.Shared.Return(map);
}

return list;
Expand All @@ -133,66 +140,13 @@ public int GetCount(bool onlyIfCheap)

internal IEnumerator<TElement> GetEnumerator(int minIdx, int maxIdx)
{
Buffer<TElement> buffer = new Buffer<TElement>(_source);
int count = buffer._count;
if (count > minIdx)
{
if (count <= maxIdx)
{
maxIdx = count - 1;
}

if (minIdx == maxIdx)
{
return GetSingleEnumerator(buffer, count, minIdx);
}
else if (count >= 32)
{
return GetLargeEnumerator(buffer, count, minIdx, maxIdx);
}

return GetSmallEnumerator(buffer, count, minIdx, maxIdx);
}

return GetEmptyEnumerator();
}

private IEnumerator<TElement> GetSingleEnumerator(Buffer<TElement> buffer, int count, int minIdx)
{
yield return GetEnumerableSorter().ElementAt(buffer._items, count, minIdx);
OrderedEnumerable<TElement> enumerator = _state == 0 && _threadId == Environment.CurrentManagedThreadId ? this : (OrderedEnumerable<TElement>)Clone();
enumerator._state = 1;
enumerator._index = minIdx;
enumerator._maxIdx = maxIdx;
return enumerator;
}

private IEnumerator<TElement> GetSmallEnumerator(Buffer<TElement> buffer, int count, int minIdx, int maxIdx)
{
int[] map = SortedMap(buffer, minIdx, maxIdx);
while (minIdx <= maxIdx)
{
yield return buffer._items[map[minIdx]];
++minIdx;
}
}

private IEnumerator<TElement> GetLargeEnumerator(Buffer<TElement> buffer, int count, int minIdx, int maxIdx)
{
int[] map = null;
try
{
map = SortedMap(buffer, minIdx, maxIdx);
while (minIdx <= maxIdx)
{
yield return buffer._items[map[minIdx]];
++minIdx;
}
}
finally
{
var rentedMap = Interlocked.Exchange(ref map, null);
if (rentedMap != null)
{
ArrayPool<int>.Shared.Return(rentedMap);
}
}
}
internal TElement[] ToArray(int minIdx, int maxIdx)
{
Buffer<TElement> buffer = new Buffer<TElement>(_source);
Expand All @@ -212,7 +166,7 @@ internal TElement[] ToArray(int minIdx, int maxIdx)
return new TElement[] { GetEnumerableSorter().ElementAt(buffer._items, count, minIdx) };
}

int[] map = SortedMap(buffer, minIdx, maxIdx);
int[] map = SortedMap(buffer, minIdx, maxIdx, true);
TElement[] array = new TElement[maxIdx - minIdx + 1];
int idx = 0;
while (minIdx <= maxIdx)
Expand All @@ -222,11 +176,7 @@ internal TElement[] ToArray(int minIdx, int maxIdx)
++minIdx;
}

if (idx >= 32)
{
ArrayPool<int>.Shared.Return(map);
}

ArrayPool<int>.Shared.Return(map);
return array;
}

Expand All @@ -249,19 +199,15 @@ internal List<TElement> ToList(int minIdx, int maxIdx)
return new List<TElement>(1) { GetEnumerableSorter().ElementAt(buffer._items, count, minIdx) };
}

int[] map = SortedMap(buffer, minIdx, maxIdx);
int[] map = SortedMap(buffer, minIdx, maxIdx, true);
List<TElement> list = new List<TElement>(maxIdx - minIdx + 1);
while (minIdx <= maxIdx)
{
list.Add(buffer._items[map[minIdx]]);
++minIdx;
}

if (list.Count >= 32)
{
ArrayPool<int>.Shared.Return(map);
}

ArrayPool<int>.Shared.Return(map);
return list;
}

Expand Down Expand Up @@ -575,6 +521,11 @@ internal OrderedEnumerable(IEnumerable<TElement> source, Func<TElement, TKey> ke
_descending = descending;
}

public override Enumerable.Iterator<TElement> Clone()
{
return new OrderedEnumerable<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
}

internal override EnumerableSorter<TElement> GetEnumerableSorter(EnumerableSorter<TElement> next)
{
EnumerableSorter<TElement> sorter = new EnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
Expand Down Expand Up @@ -678,10 +629,10 @@ internal abstract class EnumerableSorter<TElement>

internal abstract int CompareAnyKeys(int index1, int index2);

private int[] ComputeMap(TElement[] elements, int count)
private int[] ComputeMap(TElement[] elements, int count, bool rent)
{
ComputeKeys(elements, count);
int[] map = count >= 32 ? ArrayPool<int>.Shared.Rent(count) : new int[count];
int[] map = rent ? ArrayPool<int>.Shared.Rent(count) : new int[count];
for (int i = 0; i < count; i++)
{
map[i] = i;
Expand All @@ -690,30 +641,25 @@ private int[] ComputeMap(TElement[] elements, int count)
return map;
}

internal int[] Sort(TElement[] elements, int count)
internal int[] Sort(TElement[] elements, int count, bool rent)
{
int[] map = ComputeMap(elements, count);
int[] map = ComputeMap(elements, count, rent);
QuickSort(map, 0, count - 1);
return map;
}

internal int[] Sort(TElement[] elements, int count, int minIdx, int maxIdx)
internal int[] Sort(TElement[] elements, int count, int minIdx, int maxIdx, bool rent)
{
int[] map = ComputeMap(elements, count);
int[] map = ComputeMap(elements, count, rent);
PartialQuickSort(map, 0, count - 1, minIdx, maxIdx);
return map;
}

internal TElement ElementAt(TElement[] elements, int count, int idx)
{
int[] map = ComputeMap(elements, count);
int[] map = ComputeMap(elements, count, true);
var index = QuickSelect(map, count - 1, idx);

if (count >= 32)
{
ArrayPool<int>.Shared.Return(map);
}

ArrayPool<int>.Shared.Return(map);
return elements[index];
}

Expand Down