UniTask.WhenAny.Generated.tt 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. <#@ template debug="false" hostspecific="false" language="C#" #>
  2. <#@ assembly name="System.Core" #>
  3. <#@ import namespace="System.Linq" #>
  4. <#@ import namespace="System.Text" #>
  5. <#@ import namespace="System.Collections.Generic" #>
  6. <#@ output extension=".cs" #>
  7. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  8. using System;
  9. using System.Runtime.CompilerServices;
  10. using System.Runtime.ExceptionServices;
  11. using System.Threading;
  12. using Cysharp.Threading.Tasks.Internal;
  13. namespace Cysharp.Threading.Tasks
  14. {
  15. public partial struct UniTask
  16. {
  17. <# for(var i = 2; i <= 15; i++ ) {
  18. var range = Enumerable.Range(1, i);
  19. var t = string.Join(", ", range.Select(x => "T" + x));
  20. var args = string.Join(", ", range.Select(x => $"UniTask<T{x}> task{x}"));
  21. var targs = string.Join(", ", range.Select(x => $"task{x}"));
  22. var tresult = string.Join(", ", range.Select(x => $"task{x}.GetAwaiter().GetResult()"));
  23. var tBool = string.Join(", ", range.Select(x => $"T{x} result{x}"));
  24. var tfield = string.Join(", ", range.Select(x => $"self.t{x}"));
  25. Func<int, string> getResult = j => string.Join(", ", range.Select(x => (x == j) ? "result" : "default"));
  26. #>
  27. public static UniTask<(int winArgumentIndex, <#= tBool #>)> WhenAny<<#= t #>>(<#= args #>)
  28. {
  29. return new UniTask<(int winArgumentIndex, <#= tBool #>)>(new WhenAnyPromise<<#= t #>>(<#= targs #>), 0);
  30. }
  31. sealed class WhenAnyPromise<<#= t #>> : IUniTaskSource<(int, <#= tBool #>)>
  32. {
  33. int completedCount;
  34. UniTaskCompletionSourceCore<(int, <#= tBool #>)> core;
  35. public WhenAnyPromise(<#= args #>)
  36. {
  37. TaskTracker.TrackActiveTask(this, 3);
  38. this.completedCount = 0;
  39. <# for(var j = 1; j <= i; j++) { #>
  40. {
  41. var awaiter = task<#= j #>.GetAwaiter();
  42. if (awaiter.IsCompleted)
  43. {
  44. TryInvokeContinuationT<#= j #>(this, awaiter);
  45. }
  46. else
  47. {
  48. awaiter.SourceOnCompleted(state =>
  49. {
  50. using (var t = (StateTuple<WhenAnyPromise<<#= t #>>, UniTask<T<#= j #>>.Awaiter>)state)
  51. {
  52. TryInvokeContinuationT<#= j #>(t.Item1, t.Item2);
  53. }
  54. }, StateTuple.Create(this, awaiter));
  55. }
  56. }
  57. <# } #>
  58. }
  59. <# for(var j = 1; j <= i; j++) { #>
  60. static void TryInvokeContinuationT<#= j #>(WhenAnyPromise<<#= t #>> self, in UniTask<T<#= j #>>.Awaiter awaiter)
  61. {
  62. T<#= j #> result;
  63. try
  64. {
  65. result = awaiter.GetResult();
  66. }
  67. catch (Exception ex)
  68. {
  69. self.core.TrySetException(ex);
  70. return;
  71. }
  72. if (Interlocked.Increment(ref self.completedCount) == 1)
  73. {
  74. self.core.TrySetResult((<#= j - 1 #>, <#= getResult(j) #>));
  75. }
  76. }
  77. <# } #>
  78. public (int, <#= tBool #>) GetResult(short token)
  79. {
  80. TaskTracker.RemoveTracking(this);
  81. GC.SuppressFinalize(this);
  82. return core.GetResult(token);
  83. }
  84. public UniTaskStatus GetStatus(short token)
  85. {
  86. return core.GetStatus(token);
  87. }
  88. public void OnCompleted(Action<object> continuation, object state, short token)
  89. {
  90. core.OnCompleted(continuation, state, token);
  91. }
  92. public UniTaskStatus UnsafeGetStatus()
  93. {
  94. return core.UnsafeGetStatus();
  95. }
  96. void IUniTaskSource.GetResult(short token)
  97. {
  98. GetResult(token);
  99. }
  100. }
  101. <# } #>
  102. }
  103. }