OrderedAsyncEnumerable.cs 47 KB

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