OrderedAsyncEnumerable.cs 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections;
  5. using System.Collections.Generic;
  6. using System.Threading;
  7. using System.Threading.Tasks;
  8. namespace System.Linq
  9. {
  10. // NB: Large portions of the implementation are based on https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/OrderedEnumerable.cs.
  11. internal abstract class OrderedAsyncEnumerable<TElement> : AsyncIterator<TElement>, IOrderedAsyncEnumerable<TElement>, IAsyncPartition<TElement>
  12. {
  13. protected readonly IAsyncEnumerable<TElement> _source;
  14. private TElement[] _buffer;
  15. private int[] _indexes;
  16. private int _index;
  17. protected OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source)
  18. {
  19. _source = source ?? throw Error.ArgumentNull(nameof(source));
  20. }
  21. IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
  22. {
  23. return new OrderedAsyncEnumerable<TElement, TKey>(_source, keySelector, comparer, descending, this);
  24. }
  25. IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
  26. {
  27. return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, keySelector, comparer, descending, this);
  28. }
  29. IOrderedAsyncEnumerable<TElement> IOrderedAsyncEnumerable<TElement>.CreateOrderedEnumerable<TKey>(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
  30. {
  31. return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, keySelector, comparer, descending, this);
  32. }
  33. protected override async ValueTask<bool> MoveNextCore()
  34. {
  35. switch (_state)
  36. {
  37. case AsyncIteratorState.Allocated:
  38. _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
  39. var sorter = GetAsyncEnumerableSorter(_cancellationToken);
  40. _indexes = await sorter.Sort(_buffer, _buffer.Length).ConfigureAwait(false);
  41. _index = 0;
  42. _state = AsyncIteratorState.Iterating;
  43. goto case AsyncIteratorState.Iterating;
  44. case AsyncIteratorState.Iterating:
  45. if (_index < _buffer.Length)
  46. {
  47. _current = _buffer[_indexes[_index++]];
  48. return true;
  49. }
  50. await DisposeAsync().ConfigureAwait(false);
  51. break;
  52. }
  53. return false;
  54. }
  55. public override async ValueTask DisposeAsync()
  56. {
  57. _buffer = null;
  58. _indexes = null;
  59. await base.DisposeAsync().ConfigureAwait(false);
  60. }
  61. internal abstract AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken);
  62. internal AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(CancellationToken cancellationToken) => GetAsyncEnumerableSorter(next: null, cancellationToken);
  63. public async ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken)
  64. {
  65. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  66. var count = elements.Length;
  67. if (count == 0)
  68. {
  69. #if NO_ARRAY_EMPTY
  70. return EmptyArray<TElement>.Value;
  71. #else
  72. return Array.Empty<TElement>();
  73. #endif
  74. }
  75. var array = elements.Array;
  76. var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
  77. var result = new TElement[count];
  78. for (var i = 0; i < result.Length; i++)
  79. {
  80. result[i] = array[map[i]];
  81. }
  82. return result;
  83. }
  84. internal async ValueTask<TElement[]> ToArrayAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
  85. {
  86. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  87. var count = elements.Length;
  88. if (count <= minIndexInclusive)
  89. {
  90. #if NO_ARRAY_EMPTY
  91. return EmptyArray<TElement>.Value;
  92. #else
  93. return Array.Empty<TElement>();
  94. #endif
  95. }
  96. if (count <= maxIndexInclusive)
  97. {
  98. maxIndexInclusive = count - 1;
  99. }
  100. var array = elements.Array;
  101. if (minIndexInclusive == maxIndexInclusive)
  102. {
  103. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  104. var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
  105. return new TElement[] { element };
  106. }
  107. var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
  108. var result = new TElement[maxIndexInclusive - minIndexInclusive + 1];
  109. for (var i = 0; minIndexInclusive <= maxIndexInclusive; i++)
  110. {
  111. result[i] = array[map[minIndexInclusive++]];
  112. }
  113. return result;
  114. }
  115. public async ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken)
  116. {
  117. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  118. var count = elements.Length;
  119. if (count == 0)
  120. {
  121. return new List<TElement>(capacity: 0);
  122. }
  123. var array = elements.Array;
  124. var map = await SortedMap(array, count, cancellationToken).ConfigureAwait(false);
  125. var result = new List<TElement>(count);
  126. for (var i = 0; i < count; i++)
  127. {
  128. result.Add(array[map[i]]);
  129. }
  130. return result;
  131. }
  132. internal async ValueTask<List<TElement>> ToListAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
  133. {
  134. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  135. var count = elements.Length;
  136. if (count <= minIndexInclusive)
  137. {
  138. return new List<TElement>(0);
  139. }
  140. if (count <= maxIndexInclusive)
  141. {
  142. maxIndexInclusive = count - 1;
  143. }
  144. var array = elements.Array;
  145. if (minIndexInclusive == maxIndexInclusive)
  146. {
  147. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  148. var element = await sorter.ElementAt(array, count, minIndexInclusive).ConfigureAwait(false);
  149. return new List<TElement>(1) { element };
  150. }
  151. var map = await SortedMap(array, count, minIndexInclusive, maxIndexInclusive, cancellationToken).ConfigureAwait(false);
  152. var list = new List<TElement>(maxIndexInclusive - minIndexInclusive + 1);
  153. while (minIndexInclusive <= maxIndexInclusive)
  154. {
  155. list.Add(array[map[minIndexInclusive++]]);
  156. }
  157. return list;
  158. }
  159. public async ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken)
  160. {
  161. if (_source is IAsyncIListProvider<TElement> listProv)
  162. {
  163. var count = await listProv.GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
  164. }
  165. return !onlyIfCheap || _source is ICollection<TElement> || _source is ICollection ? await _source.CountAsync(cancellationToken).ConfigureAwait(false) : -1;
  166. }
  167. internal async ValueTask<int> GetCountAsync(int minIndexInclusive, int maxIndexInclusive, bool onlyIfCheap, CancellationToken cancellationToken)
  168. {
  169. var count = await GetCountAsync(onlyIfCheap, cancellationToken).ConfigureAwait(false);
  170. if (count <= 0)
  171. {
  172. return count;
  173. }
  174. if (count <= minIndexInclusive)
  175. {
  176. return 0;
  177. }
  178. return (count <= maxIndexInclusive ? count : maxIndexInclusive + 1) - minIndexInclusive;
  179. }
  180. private ValueTask<int[]> SortedMap(TElement[] elements, int count, CancellationToken cancellationToken)
  181. {
  182. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  183. return sorter.Sort(elements, count);
  184. }
  185. private ValueTask<int[]> SortedMap(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
  186. {
  187. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  188. return sorter.Sort(elements, count, minIndexInclusive, maxIndexInclusive);
  189. }
  190. private AsyncCachingComparer<TElement> GetComparer() => GetComparer(childComparer: null);
  191. internal abstract AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer);
  192. public async ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken)
  193. {
  194. #if CSHARP8
  195. await using (IAsyncEnumerator<TElement> e = _source.GetAsyncEnumerator(cancellationToken).ConfigureAwait(false))
  196. {
  197. if (!await e.MoveNextAsync())
  198. {
  199. return new Maybe<TElement>();
  200. }
  201. var value = e.Current;
  202. var comparer = GetComparer();
  203. await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
  204. while (await e.MoveNextAsync())
  205. {
  206. var x = e.Current;
  207. if (await comparer.Compare(x, cacheLower: true, cancellationToken).ConfigureAwait(false) < 0)
  208. {
  209. value = x;
  210. }
  211. }
  212. return new Maybe<TElement>(value);
  213. }
  214. #else
  215. IAsyncEnumerator<TElement> e = _source.GetAsyncEnumerator(cancellationToken);
  216. try
  217. {
  218. if (!await e.MoveNextAsync().ConfigureAwait(false))
  219. {
  220. return new Maybe<TElement>();
  221. }
  222. TElement value = e.Current;
  223. AsyncCachingComparer<TElement> comparer = GetComparer();
  224. await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
  225. while (await e.MoveNextAsync().ConfigureAwait(false))
  226. {
  227. TElement x = e.Current;
  228. if (await comparer.Compare(x, cacheLower: true, cancellationToken).ConfigureAwait(false) < 0)
  229. {
  230. value = x;
  231. }
  232. }
  233. return new Maybe<TElement>(value);
  234. }
  235. finally
  236. {
  237. await e.DisposeAsync().ConfigureAwait(false);
  238. }
  239. #endif
  240. }
  241. public async ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken)
  242. {
  243. #if CSHARP8
  244. await using (IAsyncEnumerator<TElement> e = _source.GetAsyncEnumerator(cancellationToken).ConfigureAwait(false))
  245. {
  246. if (!await e.MoveNextAsync())
  247. {
  248. return new Maybe<TElement>();
  249. }
  250. var value = e.Current;
  251. var comparer = GetComparer();
  252. await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
  253. while (await e.MoveNextAsync())
  254. {
  255. var current = e.Current;
  256. if (await comparer.Compare(current, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
  257. {
  258. value = current;
  259. }
  260. }
  261. return new Maybe<TElement>(value);
  262. }
  263. #else
  264. IAsyncEnumerator<TElement> e = _source.GetAsyncEnumerator(cancellationToken);
  265. try
  266. {
  267. if (!await e.MoveNextAsync().ConfigureAwait(false))
  268. {
  269. return new Maybe<TElement>();
  270. }
  271. TElement value = e.Current;
  272. AsyncCachingComparer<TElement> comparer = GetComparer();
  273. await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
  274. while (await e.MoveNextAsync().ConfigureAwait(false))
  275. {
  276. TElement current = e.Current;
  277. if (await comparer.Compare(current, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
  278. {
  279. value = current;
  280. }
  281. }
  282. return new Maybe<TElement>(value);
  283. }
  284. finally
  285. {
  286. await e.DisposeAsync().ConfigureAwait(false);
  287. }
  288. #endif
  289. }
  290. internal async ValueTask<Maybe<TElement>> TryGetLastAsync(int minIndexInclusive, int maxIndexInclusive, CancellationToken cancellationToken)
  291. {
  292. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  293. var count = elements.Length;
  294. if (minIndexInclusive >= count)
  295. {
  296. return new Maybe<TElement>();
  297. }
  298. var array = elements.Array;
  299. TElement last;
  300. if (maxIndexInclusive < count - 1)
  301. {
  302. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  303. last = await sorter.ElementAt(array, count, maxIndexInclusive).ConfigureAwait(false);
  304. }
  305. else
  306. {
  307. last = await Last(array, count, cancellationToken).ConfigureAwait(false);
  308. }
  309. return new Maybe<TElement>(last);
  310. }
  311. private async ValueTask<TElement> Last(TElement[] items, int count, CancellationToken cancellationToken)
  312. {
  313. var value = items[0];
  314. var comparer = GetComparer();
  315. await comparer.SetElement(value, cancellationToken).ConfigureAwait(false);
  316. for (var i = 1; i != count; ++i)
  317. {
  318. var x = items[i];
  319. if (await comparer.Compare(x, cacheLower: false, cancellationToken).ConfigureAwait(false) >= 0)
  320. {
  321. value = x;
  322. }
  323. }
  324. return value;
  325. }
  326. public IAsyncPartition<TElement> Skip(int count) => new OrderedAsyncPartition<TElement>(this, count, int.MaxValue);
  327. public IAsyncPartition<TElement> Take(int count) => new OrderedAsyncPartition<TElement>(this, 0, count - 1);
  328. public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
  329. {
  330. if (index == 0)
  331. {
  332. return TryGetFirstAsync(cancellationToken);
  333. }
  334. if (index > 0)
  335. {
  336. return Core();
  337. async ValueTask<Maybe<TElement>> Core()
  338. {
  339. var elements = await AsyncEnumerableHelpers.ToArrayWithLength(_source, cancellationToken).ConfigureAwait(false);
  340. var count = elements.Length;
  341. if (index < count)
  342. {
  343. var sorter = GetAsyncEnumerableSorter(cancellationToken);
  344. var element = await sorter.ElementAt(elements.Array, count, index).ConfigureAwait(false);
  345. return new Maybe<TElement>(element);
  346. }
  347. return new Maybe<TElement>();
  348. }
  349. }
  350. return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
  351. }
  352. }
  353. internal sealed class OrderedAsyncEnumerable<TElement, TKey> : OrderedAsyncEnumerable<TElement>
  354. {
  355. private readonly IComparer<TKey> _comparer;
  356. private readonly bool _descending;
  357. private readonly Func<TElement, TKey> _keySelector;
  358. private readonly OrderedAsyncEnumerable<TElement> _parent;
  359. public OrderedAsyncEnumerable(IAsyncEnumerable<TElement> source, Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
  360. : base(source)
  361. {
  362. _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
  363. _comparer = comparer ?? Comparer<TKey>.Default;
  364. _descending = descending;
  365. _parent = parent;
  366. }
  367. public override AsyncIteratorBase<TElement> Clone()
  368. {
  369. return new OrderedAsyncEnumerable<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
  370. }
  371. internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
  372. {
  373. var sorter = new SyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
  374. if (_parent != null)
  375. {
  376. return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
  377. }
  378. return sorter;
  379. }
  380. internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
  381. {
  382. AsyncCachingComparer<TElement> cmp = childComparer == null
  383. ? new AsyncCachingComparer<TElement, TKey>(_keySelector, _comparer, _descending)
  384. : new AsyncCachingComparerWithChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
  385. return _parent != null ? _parent.GetComparer(cmp) : cmp;
  386. }
  387. }
  388. internal sealed class OrderedAsyncEnumerableWithTask<TElement, TKey> : OrderedAsyncEnumerable<TElement>
  389. {
  390. private readonly IComparer<TKey> _comparer;
  391. private readonly bool _descending;
  392. private readonly Func<TElement, ValueTask<TKey>> _keySelector;
  393. private readonly OrderedAsyncEnumerable<TElement> _parent;
  394. public OrderedAsyncEnumerableWithTask(IAsyncEnumerable<TElement> source, Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
  395. : base(source)
  396. {
  397. _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
  398. _comparer = comparer ?? Comparer<TKey>.Default;
  399. _descending = descending;
  400. _parent = parent;
  401. }
  402. public override AsyncIteratorBase<TElement> Clone()
  403. {
  404. return new OrderedAsyncEnumerableWithTask<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
  405. }
  406. internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
  407. {
  408. var sorter = new AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey>(_keySelector, _comparer, _descending, next);
  409. if (_parent != null)
  410. {
  411. return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
  412. }
  413. return sorter;
  414. }
  415. internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
  416. {
  417. AsyncCachingComparer<TElement> cmp = childComparer == null
  418. ? new AsyncCachingComparerWithTask<TElement, TKey>(_keySelector, _comparer, _descending)
  419. : new AsyncCachingComparerWithTaskAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
  420. return _parent != null ? _parent.GetComparer(cmp) : cmp;
  421. }
  422. }
  423. #if !NO_DEEP_CANCELLATION
  424. internal sealed class OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey> : OrderedAsyncEnumerable<TElement>
  425. {
  426. private readonly IComparer<TKey> _comparer;
  427. private readonly bool _descending;
  428. private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
  429. private readonly OrderedAsyncEnumerable<TElement> _parent;
  430. public OrderedAsyncEnumerableWithTaskAndCancellation(IAsyncEnumerable<TElement> source, Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, OrderedAsyncEnumerable<TElement> parent)
  431. : base(source)
  432. {
  433. _keySelector = keySelector ?? throw Error.ArgumentNull(nameof(keySelector));
  434. _comparer = comparer ?? Comparer<TKey>.Default;
  435. _descending = descending;
  436. _parent = parent;
  437. }
  438. public override AsyncIteratorBase<TElement> Clone()
  439. {
  440. return new OrderedAsyncEnumerableWithTaskAndCancellation<TElement, TKey>(_source, _keySelector, _comparer, _descending, _parent);
  441. }
  442. internal override AsyncEnumerableSorter<TElement> GetAsyncEnumerableSorter(AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
  443. {
  444. var sorter = new AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey>(_keySelector, _comparer, _descending, next, cancellationToken);
  445. if (_parent != null)
  446. {
  447. return _parent.GetAsyncEnumerableSorter(sorter, cancellationToken);
  448. }
  449. return sorter;
  450. }
  451. internal override AsyncCachingComparer<TElement> GetComparer(AsyncCachingComparer<TElement> childComparer)
  452. {
  453. AsyncCachingComparer<TElement> cmp = childComparer == null
  454. ? new AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>(_keySelector, _comparer, _descending)
  455. : new AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey>(_keySelector, _comparer, _descending, childComparer);
  456. return _parent != null ? _parent.GetComparer(cmp) : cmp;
  457. }
  458. }
  459. #endif
  460. internal abstract class AsyncEnumerableSorter<TElement>
  461. {
  462. internal abstract ValueTask ComputeKeys(TElement[] elements, int count);
  463. internal abstract int CompareAnyKeys(int index1, int index2);
  464. public async ValueTask<int[]> Sort(TElement[] elements, int count)
  465. {
  466. var map = await ComputeMap(elements, count).ConfigureAwait(false);
  467. QuickSort(map, 0, count - 1);
  468. return map;
  469. }
  470. public async ValueTask<int[]> Sort(TElement[] elements, int count, int minIndexInclusive, int maxIndexInclusive)
  471. {
  472. var map = await ComputeMap(elements, count).ConfigureAwait(false);
  473. PartialQuickSort(map, 0, count - 1, minIndexInclusive, maxIndexInclusive);
  474. return map;
  475. }
  476. public async ValueTask<TElement> ElementAt(TElement[] elements, int count, int index)
  477. {
  478. var map = await ComputeMap(elements, count).ConfigureAwait(false);
  479. return index == 0 ?
  480. elements[Min(map, count)] :
  481. elements[QuickSelect(map, count - 1, index)];
  482. }
  483. private async ValueTask<int[]> ComputeMap(TElement[] elements, int count)
  484. {
  485. await ComputeKeys(elements, count).ConfigureAwait(false);
  486. var map = new int[count];
  487. for (var i = 0; i < count; i++)
  488. {
  489. map[i] = i;
  490. }
  491. return map;
  492. }
  493. protected abstract void QuickSort(int[] map, int left, int right);
  494. protected abstract void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive);
  495. protected abstract int QuickSelect(int[] map, int right, int idx);
  496. protected abstract int Min(int[] map, int count);
  497. }
  498. internal abstract class AsyncEnumerableSorterBase<TElement, TKey> : AsyncEnumerableSorter<TElement>
  499. {
  500. private readonly IComparer<TKey> _comparer;
  501. private readonly bool _descending;
  502. protected readonly AsyncEnumerableSorter<TElement> _next;
  503. protected TKey[] _keys;
  504. public AsyncEnumerableSorterBase(IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
  505. {
  506. _comparer = comparer;
  507. _descending = descending;
  508. _next = next;
  509. }
  510. internal sealed override int CompareAnyKeys(int index1, int index2)
  511. {
  512. var c = _comparer.Compare(_keys[index1], _keys[index2]);
  513. if (c == 0)
  514. {
  515. return _next == null ? index1 - index2 : _next.CompareAnyKeys(index1, index2);
  516. }
  517. else
  518. {
  519. return (_descending != (c > 0)) ? 1 : -1;
  520. }
  521. }
  522. private int CompareKeys(int index1, int index2) => index1 == index2 ? 0 : CompareAnyKeys(index1, index2);
  523. protected override void QuickSort(int[] map, int left, int right)
  524. {
  525. // REVIEW: Consider using Array.Sort, see https://github.com/dotnet/corefx/commit/a6aff797a33e606a60ec0c9ca034a161c609620f#diff-d90239bd8284188e2bd210790483f5ca.
  526. do
  527. {
  528. var i = left;
  529. var j = right;
  530. var x = map[i + ((j - i) >> 1)];
  531. do
  532. {
  533. while (i < map.Length && CompareKeys(x, map[i]) > 0)
  534. {
  535. i++;
  536. }
  537. while (j >= 0 && CompareKeys(x, map[j]) < 0)
  538. {
  539. j--;
  540. }
  541. if (i > j)
  542. {
  543. break;
  544. }
  545. if (i < j)
  546. {
  547. var temp = map[i];
  548. map[i] = map[j];
  549. map[j] = temp;
  550. }
  551. i++;
  552. j--;
  553. }
  554. while (i <= j);
  555. if (j - left <= right - i)
  556. {
  557. if (left < j)
  558. {
  559. QuickSort(map, left, j);
  560. }
  561. left = i;
  562. }
  563. else
  564. {
  565. if (i < right)
  566. {
  567. QuickSort(map, i, right);
  568. }
  569. right = j;
  570. }
  571. }
  572. while (left < right);
  573. }
  574. protected override void PartialQuickSort(int[] map, int left, int right, int minIndexInclusive, int maxIndexInclusive)
  575. {
  576. do
  577. {
  578. var i = left;
  579. var j = right;
  580. var x = map[i + ((j - i) >> 1)];
  581. do
  582. {
  583. while (i < map.Length && CompareKeys(x, map[i]) > 0)
  584. {
  585. i++;
  586. }
  587. while (j >= 0 && CompareKeys(x, map[j]) < 0)
  588. {
  589. j--;
  590. }
  591. if (i > j)
  592. {
  593. break;
  594. }
  595. if (i < j)
  596. {
  597. var temp = map[i];
  598. map[i] = map[j];
  599. map[j] = temp;
  600. }
  601. i++;
  602. j--;
  603. }
  604. while (i <= j);
  605. if (minIndexInclusive >= i)
  606. {
  607. left = i + 1;
  608. }
  609. else if (maxIndexInclusive <= j)
  610. {
  611. right = j - 1;
  612. }
  613. if (j - left <= right - i)
  614. {
  615. if (left < j)
  616. {
  617. PartialQuickSort(map, left, j, minIndexInclusive, maxIndexInclusive);
  618. }
  619. left = i;
  620. }
  621. else
  622. {
  623. if (i < right)
  624. {
  625. PartialQuickSort(map, i, right, minIndexInclusive, maxIndexInclusive);
  626. }
  627. right = j;
  628. }
  629. }
  630. while (left < right);
  631. }
  632. protected override int QuickSelect(int[] map, int right, int idx)
  633. {
  634. var left = 0;
  635. do
  636. {
  637. var i = left;
  638. var j = right;
  639. var x = map[i + ((j - i) >> 1)];
  640. do
  641. {
  642. while (i < map.Length && CompareKeys(x, map[i]) > 0)
  643. {
  644. i++;
  645. }
  646. while (j >= 0 && CompareKeys(x, map[j]) < 0)
  647. {
  648. j--;
  649. }
  650. if (i > j)
  651. {
  652. break;
  653. }
  654. if (i < j)
  655. {
  656. var temp = map[i];
  657. map[i] = map[j];
  658. map[j] = temp;
  659. }
  660. i++;
  661. j--;
  662. }
  663. while (i <= j);
  664. if (i <= idx)
  665. {
  666. left = i + 1;
  667. }
  668. else
  669. {
  670. right = j - 1;
  671. }
  672. if (j - left <= right - i)
  673. {
  674. if (left < j)
  675. {
  676. right = j;
  677. }
  678. left = i;
  679. }
  680. else
  681. {
  682. if (i < right)
  683. {
  684. left = i;
  685. }
  686. right = j;
  687. }
  688. }
  689. while (left < right);
  690. return map[idx];
  691. }
  692. protected override int Min(int[] map, int count)
  693. {
  694. var index = 0;
  695. for (var i = 1; i < count; i++)
  696. {
  697. if (CompareKeys(map[i], map[index]) < 0)
  698. {
  699. index = i;
  700. }
  701. }
  702. return map[index];
  703. }
  704. }
  705. internal sealed class SyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
  706. {
  707. private readonly Func<TElement, TKey> _keySelector;
  708. public SyncKeySelectorAsyncEnumerableSorter(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
  709. : base(comparer, descending, next)
  710. {
  711. _keySelector = keySelector;
  712. }
  713. internal override async ValueTask ComputeKeys(TElement[] elements, int count)
  714. {
  715. _keys = new TKey[count];
  716. for (var i = 0; i < count; i++)
  717. {
  718. _keys[i] = _keySelector(elements[i]);
  719. }
  720. if (_next != null)
  721. {
  722. await _next.ComputeKeys(elements, count).ConfigureAwait(false);
  723. }
  724. }
  725. }
  726. internal sealed class AsyncKeySelectorAsyncEnumerableSorter<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
  727. {
  728. private readonly Func<TElement, ValueTask<TKey>> _keySelector;
  729. public AsyncKeySelectorAsyncEnumerableSorter(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next)
  730. : base(comparer, descending, next)
  731. {
  732. _keySelector = keySelector;
  733. }
  734. internal override async ValueTask ComputeKeys(TElement[] elements, int count)
  735. {
  736. _keys = new TKey[count];
  737. for (var i = 0; i < count; i++)
  738. {
  739. _keys[i] = await _keySelector(elements[i]).ConfigureAwait(false);
  740. }
  741. if (_next != null)
  742. {
  743. await _next.ComputeKeys(elements, count).ConfigureAwait(false);
  744. }
  745. }
  746. }
  747. #if !NO_DEEP_CANCELLATION
  748. internal sealed class AsyncKeySelectorAsyncEnumerableSorterWithCancellation<TElement, TKey> : AsyncEnumerableSorterBase<TElement, TKey>
  749. {
  750. private readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
  751. private readonly CancellationToken _cancellationToken;
  752. public AsyncKeySelectorAsyncEnumerableSorterWithCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncEnumerableSorter<TElement> next, CancellationToken cancellationToken)
  753. : base(comparer, descending, next)
  754. {
  755. _keySelector = keySelector;
  756. _cancellationToken = cancellationToken;
  757. }
  758. internal override async ValueTask ComputeKeys(TElement[] elements, int count)
  759. {
  760. _keys = new TKey[count];
  761. for (var i = 0; i < count; i++)
  762. {
  763. _keys[i] = await _keySelector(elements[i], _cancellationToken).ConfigureAwait(false);
  764. }
  765. if (_next != null)
  766. {
  767. await _next.ComputeKeys(elements, count).ConfigureAwait(false);
  768. }
  769. }
  770. }
  771. #endif
  772. internal sealed class OrderedAsyncPartition<TElement> : AsyncIterator<TElement>, IAsyncPartition<TElement>
  773. {
  774. private readonly OrderedAsyncEnumerable<TElement> _source;
  775. private readonly int _minIndexInclusive;
  776. private readonly int _maxIndexInclusive;
  777. public OrderedAsyncPartition(OrderedAsyncEnumerable<TElement> source, int minIndexInclusive, int maxIndexInclusive)
  778. {
  779. _source = source;
  780. _minIndexInclusive = minIndexInclusive;
  781. _maxIndexInclusive = maxIndexInclusive;
  782. }
  783. public override AsyncIteratorBase<TElement> Clone() => new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, _maxIndexInclusive);
  784. public ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) =>
  785. _source.GetCountAsync(_minIndexInclusive, _maxIndexInclusive, onlyIfCheap, cancellationToken);
  786. public IAsyncPartition<TElement> Skip(int count)
  787. {
  788. var minIndex = unchecked(_minIndexInclusive + count);
  789. if (unchecked((uint)minIndex > (uint)_maxIndexInclusive))
  790. {
  791. return AsyncEnumerable.EmptyAsyncIterator<TElement>.Instance;
  792. }
  793. return new OrderedAsyncPartition<TElement>(_source, minIndex, _maxIndexInclusive);
  794. }
  795. public IAsyncPartition<TElement> Take(int count)
  796. {
  797. var maxIndex = unchecked(_minIndexInclusive + count - 1);
  798. if (unchecked((uint)maxIndex >= (uint)_maxIndexInclusive))
  799. {
  800. return this;
  801. }
  802. return new OrderedAsyncPartition<TElement>(_source, _minIndexInclusive, maxIndex);
  803. }
  804. public ValueTask<TElement[]> ToArrayAsync(CancellationToken cancellationToken) =>
  805. _source.ToArrayAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
  806. public ValueTask<List<TElement>> ToListAsync(CancellationToken cancellationToken) =>
  807. _source.ToListAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
  808. public ValueTask<Maybe<TElement>> TryGetElementAtAsync(int index, CancellationToken cancellationToken)
  809. {
  810. if (unchecked((uint)index <= (uint)(_maxIndexInclusive - _minIndexInclusive)))
  811. {
  812. return _source.TryGetElementAtAsync(index + _minIndexInclusive, cancellationToken);
  813. }
  814. return new ValueTask<Maybe<TElement>>(new Maybe<TElement>());
  815. }
  816. public ValueTask<Maybe<TElement>> TryGetFirstAsync(CancellationToken cancellationToken) =>
  817. _source.TryGetElementAtAsync(_minIndexInclusive, cancellationToken);
  818. public ValueTask<Maybe<TElement>> TryGetLastAsync(CancellationToken cancellationToken) =>
  819. _source.TryGetLastAsync(_minIndexInclusive, _maxIndexInclusive, cancellationToken);
  820. // REVIEW: Consider to tear off an iterator object rather than storing this state here?
  821. private TElement[] _buffer;
  822. private int[] _indexes;
  823. private int _minIndexIterator;
  824. private int _maxIndexIterator;
  825. protected override async ValueTask<bool> MoveNextCore()
  826. {
  827. switch (_state)
  828. {
  829. case AsyncIteratorState.Allocated:
  830. _buffer = await _source.ToArrayAsync(_cancellationToken).ConfigureAwait(false); // TODO: Use buffer.
  831. _minIndexIterator = _minIndexInclusive;
  832. _maxIndexIterator = _maxIndexInclusive;
  833. var count = _buffer.Length;
  834. if (count > _minIndexIterator)
  835. {
  836. if (count <= _maxIndexIterator)
  837. {
  838. _maxIndexIterator = count - 1;
  839. }
  840. var sorter = _source.GetAsyncEnumerableSorter(_cancellationToken);
  841. if (_minIndexIterator == _maxIndexIterator)
  842. {
  843. _current = await sorter.ElementAt(_buffer, _buffer.Length, _minIndexIterator).ConfigureAwait(false);
  844. _minIndexIterator = int.MaxValue;
  845. _maxIndexIterator = int.MinValue;
  846. _state = AsyncIteratorState.Iterating;
  847. return true;
  848. }
  849. else
  850. {
  851. _indexes = await sorter.Sort(_buffer, _buffer.Length, _minIndexIterator, _maxIndexIterator).ConfigureAwait(false);
  852. }
  853. _state = AsyncIteratorState.Iterating;
  854. goto case AsyncIteratorState.Iterating;
  855. }
  856. await DisposeAsync();
  857. break;
  858. case AsyncIteratorState.Iterating:
  859. if (_minIndexIterator <= _maxIndexIterator)
  860. {
  861. _current = _buffer[_indexes[_minIndexIterator++]];
  862. return true;
  863. }
  864. await DisposeAsync().ConfigureAwait(false);
  865. break;
  866. }
  867. return false;
  868. }
  869. public override async ValueTask DisposeAsync()
  870. {
  871. _buffer = null;
  872. _indexes = null;
  873. await base.DisposeAsync().ConfigureAwait(false);
  874. }
  875. }
  876. internal abstract class AsyncCachingComparer<TElement>
  877. {
  878. internal abstract ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken);
  879. internal abstract ValueTask SetElement(TElement element, CancellationToken cancellationToken);
  880. }
  881. internal class AsyncCachingComparer<TElement, TKey> : AsyncCachingComparer<TElement>
  882. {
  883. protected readonly Func<TElement, TKey> _keySelector;
  884. protected readonly IComparer<TKey> _comparer;
  885. protected readonly bool _descending;
  886. protected TKey _lastKey;
  887. public AsyncCachingComparer(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending)
  888. {
  889. _keySelector = keySelector;
  890. _comparer = comparer;
  891. _descending = descending;
  892. }
  893. internal override ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  894. {
  895. var newKey = _keySelector(element);
  896. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  897. if (cacheLower == cmp < 0)
  898. {
  899. _lastKey = newKey;
  900. }
  901. return new ValueTask<int>(cmp);
  902. }
  903. internal override ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  904. {
  905. _lastKey = _keySelector(element);
  906. return new ValueTask();
  907. }
  908. }
  909. internal sealed class AsyncCachingComparerWithChild<TElement, TKey> : AsyncCachingComparer<TElement, TKey>
  910. {
  911. private readonly AsyncCachingComparer<TElement> _child;
  912. public AsyncCachingComparerWithChild(Func<TElement, TKey> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
  913. : base(keySelector, comparer, descending)
  914. {
  915. _child = child;
  916. }
  917. internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  918. {
  919. var newKey = _keySelector(element);
  920. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  921. if (cmp == 0)
  922. {
  923. return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
  924. }
  925. if (cacheLower == cmp < 0)
  926. {
  927. _lastKey = newKey;
  928. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  929. }
  930. return cmp;
  931. }
  932. internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  933. {
  934. await base.SetElement(element, cancellationToken).ConfigureAwait(false);
  935. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  936. }
  937. }
  938. internal class AsyncCachingComparerWithTask<TElement, TKey> : AsyncCachingComparer<TElement>
  939. {
  940. protected readonly Func<TElement, ValueTask<TKey>> _keySelector;
  941. protected readonly IComparer<TKey> _comparer;
  942. protected readonly bool _descending;
  943. protected TKey _lastKey;
  944. public AsyncCachingComparerWithTask(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
  945. {
  946. _keySelector = keySelector;
  947. _comparer = comparer;
  948. _descending = descending;
  949. }
  950. internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  951. {
  952. var newKey = await _keySelector(element).ConfigureAwait(false);
  953. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  954. if (cacheLower == cmp < 0)
  955. {
  956. _lastKey = newKey;
  957. }
  958. return cmp;
  959. }
  960. internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  961. {
  962. _lastKey = await _keySelector(element).ConfigureAwait(false);
  963. }
  964. }
  965. internal sealed class AsyncCachingComparerWithTaskAndChild<TElement, TKey> : AsyncCachingComparerWithTask<TElement, TKey>
  966. {
  967. private readonly AsyncCachingComparer<TElement> _child;
  968. public AsyncCachingComparerWithTaskAndChild(Func<TElement, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
  969. : base(keySelector, comparer, descending)
  970. {
  971. _child = child;
  972. }
  973. internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  974. {
  975. var newKey = await _keySelector(element).ConfigureAwait(false);
  976. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  977. if (cmp == 0)
  978. {
  979. return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
  980. }
  981. if (cacheLower == cmp < 0)
  982. {
  983. _lastKey = newKey;
  984. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  985. }
  986. return cmp;
  987. }
  988. internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  989. {
  990. await base.SetElement(element, cancellationToken).ConfigureAwait(false);
  991. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  992. }
  993. }
  994. #if !NO_DEEP_CANCELLATION
  995. internal class AsyncCachingComparerWithTaskAndCancellation<TElement, TKey> : AsyncCachingComparer<TElement>
  996. {
  997. protected readonly Func<TElement, CancellationToken, ValueTask<TKey>> _keySelector;
  998. protected readonly IComparer<TKey> _comparer;
  999. protected readonly bool _descending;
  1000. protected TKey _lastKey;
  1001. public AsyncCachingComparerWithTaskAndCancellation(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending)
  1002. {
  1003. _keySelector = keySelector;
  1004. _comparer = comparer;
  1005. _descending = descending;
  1006. }
  1007. internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  1008. {
  1009. var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
  1010. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  1011. if (cacheLower == cmp < 0)
  1012. {
  1013. _lastKey = newKey;
  1014. }
  1015. return cmp;
  1016. }
  1017. internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  1018. {
  1019. _lastKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
  1020. }
  1021. }
  1022. internal sealed class AsyncCachingComparerWithTaskAndCancellationAndChild<TElement, TKey> : AsyncCachingComparerWithTaskAndCancellation<TElement, TKey>
  1023. {
  1024. private readonly AsyncCachingComparer<TElement> _child;
  1025. public AsyncCachingComparerWithTaskAndCancellationAndChild(Func<TElement, CancellationToken, ValueTask<TKey>> keySelector, IComparer<TKey> comparer, bool descending, AsyncCachingComparer<TElement> child)
  1026. : base(keySelector, comparer, descending)
  1027. {
  1028. _child = child;
  1029. }
  1030. internal override async ValueTask<int> Compare(TElement element, bool cacheLower, CancellationToken cancellationToken)
  1031. {
  1032. var newKey = await _keySelector(element, cancellationToken).ConfigureAwait(false);
  1033. var cmp = _descending ? _comparer.Compare(_lastKey, newKey) : _comparer.Compare(newKey, _lastKey);
  1034. if (cmp == 0)
  1035. {
  1036. return await _child.Compare(element, cacheLower, cancellationToken).ConfigureAwait(false);
  1037. }
  1038. if (cacheLower == cmp < 0)
  1039. {
  1040. _lastKey = newKey;
  1041. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  1042. }
  1043. return cmp;
  1044. }
  1045. internal override async ValueTask SetElement(TElement element, CancellationToken cancellationToken)
  1046. {
  1047. await base.SetElement(element, cancellationToken).ConfigureAwait(false);
  1048. await _child.SetElement(element, cancellationToken).ConfigureAwait(false);
  1049. }
  1050. }
  1051. #endif
  1052. }