12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301 |
- // Licensed to the .NET Foundation under one or more agreements.
- // The .NET Foundation licenses this file to you under the Apache 2.0 License.
- // See the LICENSE file in the project root for more information.
- using System.Collections;
- using System.Collections.Generic;
- using System.Threading;
- using System.Threading.Tasks;
- namespace System.Linq
- {
- // NB: Large portions of the implementation are based on https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/OrderedEnumerable.cs.
- internal abstract class OrderedAsyncEnumerable<TElement> : AsyncIterator<TElement>, IOrderedAsyncEnumerable<TElement>, IAsyncPartition<TElement>
- {
- protected readonly IAsyncEnumerable<TElement> _source;
- private TElement[] _buffer;
- private int[] _indexes;
- private int _index;
- protected OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source)
- {
- _source = source ?? throw Error.ArgumentNull(nameof(source));
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
- {
- return new OrderedAsyncEnumerable<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, keySelector, comparer, descending, this);
- }
- protected override async ValueTask<bool> MoveNextCore()
- {
- switch (_state)
- {
- case AsyncIteratorState.Allocated:
- _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
- var sorter = GetAsyncEnumerableSorter(_cancellationToken);
- _indexes = await sorter.Sort(_buffer, _buffer.Length).ConfigureAwait(false);
- _index = 0;
- _state = AsyncIteratorState.Iterating;
- goto case AsyncIteratorState.Iterating;
- case AsyncIteratorState.Iterating:
- if (_index < _buffer.Length)
- {
- _current = _buffer[_indexes[_index++]];
- return true;
- }
- await DisposeAsync().ConfigureAwait(false);
- break;
- }
- return false;
- }
- public override async ValueTask DisposeAsync()
- {
- _buffer = null;
- _indexes = null;
- await base.DisposeAsync().ConfigureAwait(false);
- }
- internal abstract AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken);
- internal AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(CancellationToken cancellationToken) => GetAsyncEnumerableSorter(next: null, cancellationToken);
- public async ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count == 0)
- {
- #if NO_ARRAY_EMPTY
- return EmptyArray<TElement>.Value;
- #else
- return Array.Empty<TElement>();
- #endif
- }
- var array = elements.Array;
- var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
- var result = new TElement[count];
- for (var i = 0; i < result.Length; i++)
- {
- result[i] = array[map[i]];
- }
- return result;
- }
- internal async ValueTask<TElement[]> ToArrayAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count <= minIndexInclusive)
- {
- #if NO_ARRAY_EMPTY
- return EmptyArray<TElement>.Value;
- #else
- return Array.Empty<TElement>();
- #endif
- }
- if (count <= maxIndexInclusive)
- {
- maxIndexInclusive = count - 1;
- }
- var array = elements.Array;
- if (minIndexInclusive == maxIndexInclusive)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
- return new TElement[] { element };
- }
- var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
- var result = new TElement[maxIndexInclusive - minIndexInclusive + 1];
- for (var i = 0; minIndexInclusive <= maxIndexInclusive; i++)
- {
- result[i] = array[map[minIndexInclusive++]];
- }
- return result;
- }
- public async ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count == 0)
- {
- return new List<TElement>(capacity: 0);
- }
- var array = elements.Array;
- var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
- var result = new List<TElement>(count);
- for (var i = 0; i < count; i++)
- {
- result.Add(array[map[i]]);
- }
- return result;
- }
- internal async ValueTask<List<TElement>> ToListAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (count <= minIndexInclusive)
- {
- return new List<TElement>(0);
- }
- if (count <= maxIndexInclusive)
- {
- maxIndexInclusive = count - 1;
- }
- var array = elements.Array;
- if (minIndexInclusive == maxIndexInclusive)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
- return new List<TElement>(1) { element };
- }
- var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
- var list = new List<TElement>(maxIndexInclusive - minIndexInclusive + 1);
- while (minIndexInclusive <= maxIndexInclusive)
- {
- list.Add(array[map[minIndexInclusive++]]);
- }
- return list;
- }
- public async ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
- {
- if (_source is IAsyncIListProvider<TElement> listProv)
- {
- var count = await listProv.GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
- return count;
- }
- return !onlyIfCheap || _source is ICollection<TElement> || _source is ICollection ? await _source.CountAsync(cancellationToken).ConfigureAwait(false) : -1;
- }
- internal async ValueTask<int> GetCountAsync(int minIndexInclusive, int maxIndexInclusive, bool onlyIfCheap, CancellationToken cancellationToken)
- {
- var count = await GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
- if (count <= 0)
- {
- return count;
- }
- if (count <= minIndexInclusive)
- {
- return 0;
- }
- return (count <= maxIndexInclusive ? count : maxIndexInclusive + 1) - minIndexInclusive;
- }
- private ValueTask<int[]> SortedMap(TElement[] elements, int count, CancellationToken cancellationToken)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- return sorter.Sort(elements, count);
- }
- private ValueTask<int[]> SortedMap(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- return sorter.Sort(elements, count, minIndexInclusive, maxIndexInclusive);
- }
- private AsyncCachingComparer<TElement> GetComparer() => GetComparer(childComparer: null);
- internal abstract AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer);
- public async ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken)
- {
- var e = _source.GetConfiguredAsyncEnumerator(cancellationToken, false);
- try // TODO: Switch to `await using` in preview 3 (https://github.com/dotnet/roslyn/pull/32731)
- {
- if (!await e.MoveNextAsync())
- {
- return new Maybe<TElement>();
- }
- var value = e.Current;
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- while (await e.MoveNextAsync())
- {
- var x = e.Current;
- if (await comparer.Compare(x, cacheLower: true, cancellationToken).ConfigureAwait(false) < 0)
- {
- value = x;
- }
- }
- return new Maybe<TElement>(value);
- }
- finally
- {
- await e.DisposeAsync();
- }
- }
- public async ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken)
- {
- var e = _source.GetConfiguredAsyncEnumerator(cancellationToken, false);
- try // TODO: Switch to `await using` in preview 3 (https://github.com/dotnet/roslyn/pull/32731)
- {
- if (!await e.MoveNextAsync())
- {
- return new Maybe<TElement>();
- }
- var value = e.Current;
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- while (await e.MoveNextAsync())
- {
- var current = e.Current;
- if (await comparer.Compare(current, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
- {
- value = current;
- }
- }
- return new Maybe<TElement>(value);
- }
- finally
- {
- await e.DisposeAsync();
- }
- }
- internal async ValueTask<Maybe<TElement>> TryGetLastAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (minIndexInclusive >= count)
- {
- return new Maybe<TElement>();
- }
- var array = elements.Array;
- TElement last;
- if (maxIndexInclusive < count - 1)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- last = await sorter.ElementAt(array, count, maxIndexInclusive).ConfigureAwait(false);
- }
- else
- {
- last = await Last(array, count, cancellationToken).ConfigureAwait(false);
- }
- return new Maybe<TElement>(last);
- }
- private async ValueTask<TElement> Last(TElement[] items, int count, CancellationToken cancellationToken)
- {
- var value = items[0];
- var comparer = GetComparer();
- await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
- for (var i = 1; i != count; ++i)
- {
- var x = items[i];
- if (await comparer.Compare(x, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
- {
- value = x;
- }
- }
- return value;
- }
- public IAsyncPartition<TElement> Skip(int count) => new OrderedAsyncPartition<TElement>(this, count, int.MaxValue);
- public IAsyncPartition<TElement> Take(int count) => new OrderedAsyncPartition<TElement>(this, 0, count - 1);
- public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
- {
- if (index == 0)
- {
- return TryGetFirstAsync(cancellationToken);
- }
- if (index > 0)
- {
- return Core();
- async ValueTask<Maybe<TElement>> Core()
- {
- var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
- var count = elements.Length;
- if (index < count)
- {
- var sorter = GetAsyncEnumerableSorter(cancellationToken);
- var element = await sorter.ElementAt(elements.Array, count, index).ConfigureAwait(false);
- return new Maybe<TElement>(element);
- }
- return new Maybe<TElement>();
- }
- }
- return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
- }
- }
- internal sealed class OrderedAsyncEnumerable<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, TKey> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement> _parent;
- public OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerable<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
- {
- var sorter = new SyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparer<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- internal sealed class OrderedAsyncEnumerableWithTask<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, ValueTask<TKey>> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement> _parent;
- public OrderedAsyncEnumerableWithTask(IAsyncEnumerable<TElement> source, Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
- {
- var sorter = new AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparerWithTask<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithTaskAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal sealed class OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey> : OrderedAsyncEnumerable<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- private readonly OrderedAsyncEnumerable<TElement> _parent;
- public OrderedAsyncEnumerableWithTaskAndCancellation(IAsyncEnumerable<TElement> source, Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
- : base(source)
- {
- _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
- _comparer = comparer ?? Comparer<TKey>.Default;
- _descending = descending;
- _parent = parent;
- }
- public override AsyncIteratorBase<TElement> Clone()
- {
- return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
- }
- internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
- {
- var sorter = new AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey>(_keySelector, _comparer, _descending, next, cancellationToken);
- if (_parent != null)
- {
- return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
- }
- return sorter;
- }
- internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
- {
- AsyncCachingComparer<TElement> cmp = childComparer == null
- ? new AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>(_keySelector, _comparer, _descending)
- : new AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
- return _parent != null ? _parent.GetComparer(cmp) : cmp;
- }
- }
- #endif
- internal abstract class AsyncEnumerableSorter<TElement>
- {
- internal abstract ValueTask ComputeKeys(TElement[] elements, int count);
- internal abstract int CompareAnyKeys(int index1, int index2);
- public async ValueTask<int[]> Sort(TElement[] elements, int count)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- QuickSort(map, 0, count - 1);
- return map;
- }
- public async ValueTask<int[]> Sort(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- PartialQuickSort(map, 0, count - 1, minIndexInclusive, maxIndexInclusive);
- return map;
- }
- public async ValueTask<TElement> ElementAt(TElement[] elements, int count, int index)
- {
- var map = await ComputeMap(elements, count).ConfigureAwait(false);
- return index == 0 ?
- elements[Min(map, count)] :
- elements[QuickSelect(map, count - 1, index)];
- }
- private async ValueTask<int[]> ComputeMap(TElement[] elements, int count)
- {
- await ComputeKeys(elements, count).ConfigureAwait(false);
- var map = new int[count];
- for (var i = 0; i < count; i++)
- {
- map[i] = i;
- }
- return map;
- }
- protected abstract void QuickSort(int[] map, int left, int right);
- protected abstract void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive);
- protected abstract int QuickSelect(int[] map, int right, int idx);
- protected abstract int Min(int[] map, int count);
- }
- internal abstract class AsyncEnumerableSorterBase<TElement, TKey> : AsyncEnumerableSorter<TElement>
- {
- private readonly IComparer<TKey> _comparer;
- private readonly bool _descending;
- protected readonly AsyncEnumerableSorter<TElement> _next;
- protected TKey[] _keys;
- public AsyncEnumerableSorterBase(IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
- {
- _comparer = comparer;
- _descending = descending;
- _next = next;
- }
- internal sealed override int CompareAnyKeys(int index1, int index2)
- {
- var c = _comparer.Compare(_keys[index1], _keys[index2]);
- if (c == 0)
- {
- return _next == null ? index1 - index2 : _next.CompareAnyKeys(index1, index2);
- }
- else
- {
- return (_descending != (c > 0)) ? 1 : -1;
- }
- }
- private int CompareKeys(int index1, int index2) => index1 == index2 ? 0 : CompareAnyKeys(index1, index2);
- protected override void QuickSort(int[] map, int left, int right)
- {
- // REVIEW: Consider using Array.Sort, see https://github.com/dotnet/corefx/commit/a6aff797a33e606a60ec0c9ca034a161c609620f#diff-d90239bd8284188e2bd210790483f5ca.
- do
- {
- var i = left;
- var j = right;
- var x = map[i + ((j - i) >> 1)];
- do
- {
- while (i < map.Length && CompareKeys(x, map[i]) > 0)
- {
- i++;
- }
- while (j >= 0 && CompareKeys(x, map[j]) < 0)
- {
- j--;
- }
- if (i > j)
- {
- break;
- }
- if (i < j)
- {
- var temp = map[i];
- map[i] = map[j];
- map[j] = temp;
- }
- i++;
- j--;
- }
- while (i <= j);
- if (j - left <= right - i)
- {
- if (left < j)
- {
- QuickSort(map, left, j);
- }
- left = i;
- }
- else
- {
- if (i < right)
- {
- QuickSort(map, i, right);
- }
- right = j;
- }
- }
- while (left < right);
- }
- protected override void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive)
- {
- do
- {
- var i = left;
- var j = right;
- var x = map[i + ((j - i) >> 1)];
- do
- {
- while (i < map.Length && CompareKeys(x, map[i]) > 0)
- {
- i++;
- }
- while (j >= 0 && CompareKeys(x, map[j]) < 0)
- {
- j--;
- }
- if (i > j)
- {
- break;
- }
- if (i < j)
- {
- var temp = map[i];
- map[i] = map[j];
- map[j] = temp;
- }
- i++;
- j--;
- }
- while (i <= j);
- if (minIndexInclusive >= i)
- {
- left = i + 1;
- }
- else if (maxIndexInclusive <= j)
- {
- right = j - 1;
- }
- if (j - left <= right - i)
- {
- if (left < j)
- {
- PartialQuickSort(map, left, j, minIndexInclusive, maxIndexInclusive);
- }
- left = i;
- }
- else
- {
- if (i < right)
- {
- PartialQuickSort(map, i, right, minIndexInclusive, maxIndexInclusive);
- }
- right = j;
- }
- }
- while (left < right);
- }
- protected override int QuickSelect(int[] map, int right, int idx)
- {
- var left = 0;
- do
- {
- var i = left;
- var j = right;
- var x = map[i + ((j - i) >> 1)];
- do
- {
- while (i < map.Length && CompareKeys(x, map[i]) > 0)
- {
- i++;
- }
- while (j >= 0 && CompareKeys(x, map[j]) < 0)
- {
- j--;
- }
- if (i > j)
- {
- break;
- }
- if (i < j)
- {
- var temp = map[i];
- map[i] = map[j];
- map[j] = temp;
- }
- i++;
- j--;
- }
- while (i <= j);
- if (i <= idx)
- {
- left = i + 1;
- }
- else
- {
- right = j - 1;
- }
- if (j - left <= right - i)
- {
- if (left < j)
- {
- right = j;
- }
- left = i;
- }
- else
- {
- if (i < right)
- {
- left = i;
- }
- right = j;
- }
- }
- while (left < right);
- return map[idx];
- }
- protected override int Min(int[] map, int count)
- {
- var index = 0;
- for (var i = 1; i < count; i++)
- {
- if (CompareKeys(map[i], map[index]) < 0)
- {
- index = i;
- }
- }
- return map[index];
- }
- }
- internal sealed class SyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, TKey> _keySelector;
- public SyncKeySelectorAsyncEnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = _keySelector(elements[i]);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- internal sealed class AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, ValueTask<TKey>> _keySelector;
- public AsyncKeySelectorAsyncEnumerableSorter(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = await _keySelector(elements[i]).ConfigureAwait(false);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal sealed class AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
- {
- private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- private readonly CancellationToken _cancellationToken;
- public AsyncKeySelectorAsyncEnumerableSorterWithCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
- : base(comparer, descending, next)
- {
- _keySelector = keySelector;
- _cancellationToken = cancellationToken;
- }
- internal override async ValueTask ComputeKeys(TElement[] elements, int count)
- {
- _keys = new TKey[count];
- for (var i = 0; i < count; i++)
- {
- _keys[i] = await _keySelector(elements[i], _cancellationToken).ConfigureAwait(false);
- }
- if (_next != null)
- {
- await _next.ComputeKeys(elements, count).ConfigureAwait(false);
- }
- }
- }
- #endif
- internal sealed class OrderedAsyncPartition<TElement> : AsyncIterator<TElement>, IAsyncPartition<TElement>
- {
- private readonly OrderedAsyncEnumerable<TElement> _source;
- private readonly int _minIndexInclusive;
- private readonly int _maxIndexInclusive;
- public OrderedAsyncPartition(OrderedAsyncEnumerable<TElement> source, int minIndexInclusive, int maxIndexInclusive)
- {
- _source = source;
- _minIndexInclusive = minIndexInclusive;
- _maxIndexInclusive = maxIndexInclusive;
- }
- public override AsyncIteratorBase<TElement> Clone() => new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, _maxIndexInclusive);
- public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) =>
- _source.GetCountAsync(_minIndexInclusive, _maxIndexInclusive, onlyIfCheap, cancellationToken);
- public IAsyncPartition<TElement> Skip(int count)
- {
- var minIndex = unchecked(_minIndexInclusive + count);
- if (unchecked((uint)minIndex > (uint)_maxIndexInclusive))
- {
- return AsyncEnumerable.EmptyAsyncIterator<TElement>.Instance;
- }
-
- return new OrderedAsyncPartition<TElement>(_source, minIndex, _maxIndexInclusive);
- }
- public IAsyncPartition<TElement> Take(int count)
- {
- var maxIndex = unchecked(_minIndexInclusive + count - 1);
- if (unchecked((uint)maxIndex >= (uint)_maxIndexInclusive))
- {
- return this;
- }
- return new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, maxIndex);
- }
- public ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken) =>
- _source.ToArrayAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- public ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken) =>
- _source.ToListAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
- {
- if (unchecked((uint)index <= (uint)(_maxIndexInclusive - _minIndexInclusive)))
- {
- return _source.TryGetElementAtAsync(index + _minIndexInclusive, cancellationToken);
- }
- return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
- }
- public ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken) =>
- _source.TryGetElementAtAsync(_minIndexInclusive, cancellationToken);
- public ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken) =>
- _source.TryGetLastAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
- // REVIEW: Consider to tear off an iterator object rather than storing this state here?
- private TElement[] _buffer;
- private int[] _indexes;
- private int _minIndexIterator;
- private int _maxIndexIterator;
- protected override async ValueTask<bool> MoveNextCore()
- {
- switch (_state)
- {
- case AsyncIteratorState.Allocated:
- _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
- _minIndexIterator = _minIndexInclusive;
- _maxIndexIterator = _maxIndexInclusive;
- var count = _buffer.Length;
- if (count > _minIndexIterator)
- {
- if (count <= _maxIndexIterator)
- {
- _maxIndexIterator = count - 1;
- }
- var sorter = _source.GetAsyncEnumerableSorter(_cancellationToken);
- if (_minIndexIterator == _maxIndexIterator)
- {
- _current = await sorter.ElementAt(_buffer, _buffer.Length, _minIndexIterator).ConfigureAwait(false);
- _minIndexIterator = int.MaxValue;
- _maxIndexIterator = int.MinValue;
- _state = AsyncIteratorState.Iterating;
- return true;
- }
- else
- {
- _indexes = await sorter.Sort(_buffer, _buffer.Length, _minIndexIterator, _maxIndexIterator).ConfigureAwait(false);
- }
- _state = AsyncIteratorState.Iterating;
- goto case AsyncIteratorState.Iterating;
- }
- await DisposeAsync();
- break;
- case AsyncIteratorState.Iterating:
- if (_minIndexIterator <= _maxIndexIterator)
- {
- _current = _buffer[_indexes[_minIndexIterator++]];
- return true;
- }
- await DisposeAsync().ConfigureAwait(false);
- break;
- }
- return false;
- }
- public override async ValueTask DisposeAsync()
- {
- _buffer = null;
- _indexes = null;
- await base.DisposeAsync().ConfigureAwait(false);
- }
- }
- internal abstract class AsyncCachingComparer<TElement>
- {
- internal abstract ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken);
- internal abstract ValueTask SetElement(TElement element, CancellationToken cancellationToken);
- }
- internal class AsyncCachingComparer<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, TKey> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparer(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- }
- internal override ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = _keySelector(element);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return new ValueTask<int>(cmp);
- }
- internal override ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = _keySelector(element);
- return new ValueTask();
- }
- }
- internal sealed class AsyncCachingComparerWithChild<TElement, TKey> : AsyncCachingComparer<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithChild(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = _keySelector(element);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- internal class AsyncCachingComparerWithTask<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, ValueTask<TKey>> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparerWithTask(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = await _keySelector(element).ConfigureAwait(false);
- }
- }
- internal sealed class AsyncCachingComparerWithTaskAndChild<TElement, TKey> : AsyncCachingComparerWithTask<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithTaskAndChild(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- #if !NO_DEEP_CANCELLATION
- internal class AsyncCachingComparerWithTaskAndCancellation<TElement, TKey> : AsyncCachingComparer<TElement>
- {
- protected readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
- protected readonly IComparer<TKey> _comparer;
- protected readonly bool _descending;
- protected TKey _lastKey;
- public AsyncCachingComparerWithTaskAndCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
- {
- _keySelector = keySelector;
- _comparer = comparer;
- _descending = descending;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- _lastKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- }
- }
- internal sealed class AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey> : AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>
- {
- private readonly AsyncCachingComparer<TElement> _child;
- public AsyncCachingComparerWithTaskAndCancellationAndChild(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
- : base(keySelector, comparer, descending)
- {
- _child = child;
- }
- internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
- {
- var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
- var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
- if (cmp == 0)
- {
- return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
- }
- if (cacheLower == cmp < 0)
- {
- _lastKey = newKey;
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- return cmp;
- }
- internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
- {
- await base.SetElement(element, cancellationToken).ConfigureAwait(false);
- await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
- }
- }
- #endif
- }
|