選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 

702 行
23 KiB

  1. #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
  2. using Cysharp.Threading.Tasks.Internal;
  3. using System;
  4. using System.Runtime.CompilerServices;
  5. using System.Runtime.ExceptionServices;
  6. using System.Threading;
  7. namespace Cysharp.Threading.Tasks
  8. {
  9. public partial struct UniTask
  10. {
  11. static readonly UniTask CanceledUniTask = new Func<UniTask>(() =>
  12. {
  13. return new UniTask(new CanceledResultSource(CancellationToken.None), 0);
  14. })();
  15. static class CanceledUniTaskCache<T>
  16. {
  17. public static readonly UniTask<T> Task;
  18. static CanceledUniTaskCache()
  19. {
  20. Task = new UniTask<T>(new CanceledResultSource<T>(CancellationToken.None), 0);
  21. }
  22. }
  23. public static readonly UniTask CompletedTask = new UniTask();
  24. public static UniTask FromException(Exception ex)
  25. {
  26. if (ex is OperationCanceledException oce)
  27. {
  28. return FromCanceled(oce.CancellationToken);
  29. }
  30. return new UniTask(new ExceptionResultSource(ex), 0);
  31. }
  32. public static UniTask<T> FromException<T>(Exception ex)
  33. {
  34. if (ex is OperationCanceledException oce)
  35. {
  36. return FromCanceled<T>(oce.CancellationToken);
  37. }
  38. return new UniTask<T>(new ExceptionResultSource<T>(ex), 0);
  39. }
  40. public static UniTask<T> FromResult<T>(T value)
  41. {
  42. return new UniTask<T>(value);
  43. }
  44. public static UniTask FromCanceled(CancellationToken cancellationToken = default)
  45. {
  46. if (cancellationToken == CancellationToken.None)
  47. {
  48. return CanceledUniTask;
  49. }
  50. else
  51. {
  52. return new UniTask(new CanceledResultSource(cancellationToken), 0);
  53. }
  54. }
  55. public static UniTask<T> FromCanceled<T>(CancellationToken cancellationToken = default)
  56. {
  57. if (cancellationToken == CancellationToken.None)
  58. {
  59. return CanceledUniTaskCache<T>.Task;
  60. }
  61. else
  62. {
  63. return new UniTask<T>(new CanceledResultSource<T>(cancellationToken), 0);
  64. }
  65. }
  66. public static UniTask Create(Func<UniTask> factory)
  67. {
  68. return factory();
  69. }
  70. public static UniTask Create(Func<CancellationToken, UniTask> factory, CancellationToken cancellationToken)
  71. {
  72. return factory(cancellationToken);
  73. }
  74. public static UniTask Create<T>(T state, Func<T, UniTask> factory)
  75. {
  76. return factory(state);
  77. }
  78. public static UniTask<T> Create<T>(Func<UniTask<T>> factory)
  79. {
  80. return factory();
  81. }
  82. public static AsyncLazy Lazy(Func<UniTask> factory)
  83. {
  84. return new AsyncLazy(factory);
  85. }
  86. public static AsyncLazy<T> Lazy<T>(Func<UniTask<T>> factory)
  87. {
  88. return new AsyncLazy<T>(factory);
  89. }
  90. /// <summary>
  91. /// helper of fire and forget void action.
  92. /// </summary>
  93. public static void Void(Func<UniTaskVoid> asyncAction)
  94. {
  95. asyncAction().Forget();
  96. }
  97. /// <summary>
  98. /// helper of fire and forget void action.
  99. /// </summary>
  100. public static void Void(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  101. {
  102. asyncAction(cancellationToken).Forget();
  103. }
  104. /// <summary>
  105. /// helper of fire and forget void action.
  106. /// </summary>
  107. public static void Void<T>(Func<T, UniTaskVoid> asyncAction, T state)
  108. {
  109. asyncAction(state).Forget();
  110. }
  111. /// <summary>
  112. /// helper of create add UniTaskVoid to delegate.
  113. /// For example: FooAction = UniTask.Action(async () => { /* */ })
  114. /// </summary>
  115. public static Action Action(Func<UniTaskVoid> asyncAction)
  116. {
  117. return () => asyncAction().Forget();
  118. }
  119. /// <summary>
  120. /// helper of create add UniTaskVoid to delegate.
  121. /// </summary>
  122. public static Action Action(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  123. {
  124. return () => asyncAction(cancellationToken).Forget();
  125. }
  126. /// <summary>
  127. /// helper of create add UniTaskVoid to delegate.
  128. /// </summary>
  129. public static Action Action<T>(T state, Func<T, UniTaskVoid> asyncAction)
  130. {
  131. return () => asyncAction(state).Forget();
  132. }
  133. #if UNITY_2018_3_OR_NEWER
  134. /// <summary>
  135. /// Create async void(UniTaskVoid) UnityAction.
  136. /// For example: onClick.AddListener(UniTask.UnityAction(async () => { /* */ } ))
  137. /// </summary>
  138. public static UnityEngine.Events.UnityAction UnityAction(Func<UniTaskVoid> asyncAction)
  139. {
  140. return () => asyncAction().Forget();
  141. }
  142. /// <summary>
  143. /// Create async void(UniTaskVoid) UnityAction.
  144. /// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, this.GetCancellationTokenOnDestroy()))
  145. /// </summary>
  146. public static UnityEngine.Events.UnityAction UnityAction(Func<CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  147. {
  148. return () => asyncAction(cancellationToken).Forget();
  149. }
  150. /// <summary>
  151. /// Create async void(UniTaskVoid) UnityAction.
  152. /// For example: onClick.AddListener(UniTask.UnityAction(FooAsync, Argument))
  153. /// </summary>
  154. public static UnityEngine.Events.UnityAction UnityAction<T>(T state, Func<T, UniTaskVoid> asyncAction)
  155. {
  156. return () => asyncAction(state).Forget();
  157. }
  158. /// <summary>
  159. /// Create async void(UniTaskVoid) UnityAction.
  160. /// For example: onClick.AddListener(UniTask.UnityAction(async (T arg) => { /* */ } ))
  161. /// </summary>
  162. public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, UniTaskVoid> asyncAction)
  163. {
  164. return (arg) => asyncAction(arg).Forget();
  165. }
  166. /// <summary>
  167. /// Create async void(UniTaskVoid) UnityAction.
  168. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1) => { /* */ } ))
  169. /// </summary>
  170. public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, UniTaskVoid> asyncAction)
  171. {
  172. return (arg0, arg1) => asyncAction(arg0, arg1).Forget();
  173. }
  174. /// <summary>
  175. /// Create async void(UniTaskVoid) UnityAction.
  176. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2) => { /* */ } ))
  177. /// </summary>
  178. public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, UniTaskVoid> asyncAction)
  179. {
  180. return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2).Forget();
  181. }
  182. /// <summary>
  183. /// Create async void(UniTaskVoid) UnityAction.
  184. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3) => { /* */ } ))
  185. /// </summary>
  186. public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, UniTaskVoid> asyncAction)
  187. {
  188. return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3).Forget();
  189. }
  190. // <summary>
  191. /// Create async void(UniTaskVoid) UnityAction.
  192. /// For example: onClick.AddListener(UniTask.UnityAction(async (T arg, CancellationToken cancellationToken) => { /* */ } ))
  193. /// </summary>
  194. public static UnityEngine.Events.UnityAction<T> UnityAction<T>(Func<T, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  195. {
  196. return (arg) => asyncAction(arg, cancellationToken).Forget();
  197. }
  198. /// <summary>
  199. /// Create async void(UniTaskVoid) UnityAction.
  200. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, CancellationToken cancellationToken) => { /* */ } ))
  201. /// </summary>
  202. public static UnityEngine.Events.UnityAction<T0, T1> UnityAction<T0, T1>(Func<T0, T1, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  203. {
  204. return (arg0, arg1) => asyncAction(arg0, arg1, cancellationToken).Forget();
  205. }
  206. /// <summary>
  207. /// Create async void(UniTaskVoid) UnityAction.
  208. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, CancellationToken cancellationToken) => { /* */ } ))
  209. /// </summary>
  210. public static UnityEngine.Events.UnityAction<T0, T1, T2> UnityAction<T0, T1, T2>(Func<T0, T1, T2, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  211. {
  212. return (arg0, arg1, arg2) => asyncAction(arg0, arg1, arg2, cancellationToken).Forget();
  213. }
  214. /// <summary>
  215. /// Create async void(UniTaskVoid) UnityAction.
  216. /// For example: onClick.AddListener(UniTask.UnityAction(async (T0 arg0, T1 arg1, T2 arg2, T3 arg3, CancellationToken cancellationToken) => { /* */ } ))
  217. /// </summary>
  218. public static UnityEngine.Events.UnityAction<T0, T1, T2, T3> UnityAction<T0, T1, T2, T3>(Func<T0, T1, T2, T3, CancellationToken, UniTaskVoid> asyncAction, CancellationToken cancellationToken)
  219. {
  220. return (arg0, arg1, arg2, arg3) => asyncAction(arg0, arg1, arg2, arg3, cancellationToken).Forget();
  221. }
  222. #endif
  223. /// <summary>
  224. /// Defer the task creation just before call await.
  225. /// </summary>
  226. public static UniTask Defer(Func<UniTask> factory)
  227. {
  228. return new UniTask(new DeferPromise(factory), 0);
  229. }
  230. /// <summary>
  231. /// Defer the task creation just before call await.
  232. /// </summary>
  233. public static UniTask<T> Defer<T>(Func<UniTask<T>> factory)
  234. {
  235. return new UniTask<T>(new DeferPromise<T>(factory), 0);
  236. }
  237. /// <summary>
  238. /// Defer the task creation just before call await.
  239. /// </summary>
  240. public static UniTask Defer<TState>(TState state, Func<TState, UniTask> factory)
  241. {
  242. return new UniTask(new DeferPromiseWithState<TState>(state, factory), 0);
  243. }
  244. /// <summary>
  245. /// Defer the task creation just before call await.
  246. /// </summary>
  247. public static UniTask<TResult> Defer<TState, TResult>(TState state, Func<TState, UniTask<TResult>> factory)
  248. {
  249. return new UniTask<TResult>(new DeferPromiseWithState<TState, TResult>(state, factory), 0);
  250. }
  251. /// <summary>
  252. /// Never complete.
  253. /// </summary>
  254. public static UniTask Never(CancellationToken cancellationToken)
  255. {
  256. return new UniTask<AsyncUnit>(new NeverPromise<AsyncUnit>(cancellationToken), 0);
  257. }
  258. /// <summary>
  259. /// Never complete.
  260. /// </summary>
  261. public static UniTask<T> Never<T>(CancellationToken cancellationToken)
  262. {
  263. return new UniTask<T>(new NeverPromise<T>(cancellationToken), 0);
  264. }
  265. sealed class ExceptionResultSource : IUniTaskSource
  266. {
  267. readonly ExceptionDispatchInfo exception;
  268. bool calledGet;
  269. public ExceptionResultSource(Exception exception)
  270. {
  271. this.exception = ExceptionDispatchInfo.Capture(exception);
  272. }
  273. public void GetResult(short token)
  274. {
  275. if (!calledGet)
  276. {
  277. calledGet = true;
  278. GC.SuppressFinalize(this);
  279. }
  280. exception.Throw();
  281. }
  282. public UniTaskStatus GetStatus(short token)
  283. {
  284. return UniTaskStatus.Faulted;
  285. }
  286. public UniTaskStatus UnsafeGetStatus()
  287. {
  288. return UniTaskStatus.Faulted;
  289. }
  290. public void OnCompleted(Action<object> continuation, object state, short token)
  291. {
  292. continuation(state);
  293. }
  294. ~ExceptionResultSource()
  295. {
  296. if (!calledGet)
  297. {
  298. UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
  299. }
  300. }
  301. }
  302. sealed class ExceptionResultSource<T> : IUniTaskSource<T>
  303. {
  304. readonly ExceptionDispatchInfo exception;
  305. bool calledGet;
  306. public ExceptionResultSource(Exception exception)
  307. {
  308. this.exception = ExceptionDispatchInfo.Capture(exception);
  309. }
  310. public T GetResult(short token)
  311. {
  312. if (!calledGet)
  313. {
  314. calledGet = true;
  315. GC.SuppressFinalize(this);
  316. }
  317. exception.Throw();
  318. return default;
  319. }
  320. void IUniTaskSource.GetResult(short token)
  321. {
  322. if (!calledGet)
  323. {
  324. calledGet = true;
  325. GC.SuppressFinalize(this);
  326. }
  327. exception.Throw();
  328. }
  329. public UniTaskStatus GetStatus(short token)
  330. {
  331. return UniTaskStatus.Faulted;
  332. }
  333. public UniTaskStatus UnsafeGetStatus()
  334. {
  335. return UniTaskStatus.Faulted;
  336. }
  337. public void OnCompleted(Action<object> continuation, object state, short token)
  338. {
  339. continuation(state);
  340. }
  341. ~ExceptionResultSource()
  342. {
  343. if (!calledGet)
  344. {
  345. UniTaskScheduler.PublishUnobservedTaskException(exception.SourceException);
  346. }
  347. }
  348. }
  349. sealed class CanceledResultSource : IUniTaskSource
  350. {
  351. readonly CancellationToken cancellationToken;
  352. public CanceledResultSource(CancellationToken cancellationToken)
  353. {
  354. this.cancellationToken = cancellationToken;
  355. }
  356. public void GetResult(short token)
  357. {
  358. throw new OperationCanceledException(cancellationToken);
  359. }
  360. public UniTaskStatus GetStatus(short token)
  361. {
  362. return UniTaskStatus.Canceled;
  363. }
  364. public UniTaskStatus UnsafeGetStatus()
  365. {
  366. return UniTaskStatus.Canceled;
  367. }
  368. public void OnCompleted(Action<object> continuation, object state, short token)
  369. {
  370. continuation(state);
  371. }
  372. }
  373. sealed class CanceledResultSource<T> : IUniTaskSource<T>
  374. {
  375. readonly CancellationToken cancellationToken;
  376. public CanceledResultSource(CancellationToken cancellationToken)
  377. {
  378. this.cancellationToken = cancellationToken;
  379. }
  380. public T GetResult(short token)
  381. {
  382. throw new OperationCanceledException(cancellationToken);
  383. }
  384. void IUniTaskSource.GetResult(short token)
  385. {
  386. throw new OperationCanceledException(cancellationToken);
  387. }
  388. public UniTaskStatus GetStatus(short token)
  389. {
  390. return UniTaskStatus.Canceled;
  391. }
  392. public UniTaskStatus UnsafeGetStatus()
  393. {
  394. return UniTaskStatus.Canceled;
  395. }
  396. public void OnCompleted(Action<object> continuation, object state, short token)
  397. {
  398. continuation(state);
  399. }
  400. }
  401. sealed class DeferPromise : IUniTaskSource
  402. {
  403. Func<UniTask> factory;
  404. UniTask task;
  405. UniTask.Awaiter awaiter;
  406. public DeferPromise(Func<UniTask> factory)
  407. {
  408. this.factory = factory;
  409. }
  410. public void GetResult(short token)
  411. {
  412. awaiter.GetResult();
  413. }
  414. public UniTaskStatus GetStatus(short token)
  415. {
  416. var f = Interlocked.Exchange(ref factory, null);
  417. if (f != null)
  418. {
  419. task = f();
  420. awaiter = task.GetAwaiter();
  421. }
  422. return task.Status;
  423. }
  424. public void OnCompleted(Action<object> continuation, object state, short token)
  425. {
  426. awaiter.SourceOnCompleted(continuation, state);
  427. }
  428. public UniTaskStatus UnsafeGetStatus()
  429. {
  430. return task.Status;
  431. }
  432. }
  433. sealed class DeferPromise<T> : IUniTaskSource<T>
  434. {
  435. Func<UniTask<T>> factory;
  436. UniTask<T> task;
  437. UniTask<T>.Awaiter awaiter;
  438. public DeferPromise(Func<UniTask<T>> factory)
  439. {
  440. this.factory = factory;
  441. }
  442. public T GetResult(short token)
  443. {
  444. return awaiter.GetResult();
  445. }
  446. void IUniTaskSource.GetResult(short token)
  447. {
  448. awaiter.GetResult();
  449. }
  450. public UniTaskStatus GetStatus(short token)
  451. {
  452. var f = Interlocked.Exchange(ref factory, null);
  453. if (f != null)
  454. {
  455. task = f();
  456. awaiter = task.GetAwaiter();
  457. }
  458. return task.Status;
  459. }
  460. public void OnCompleted(Action<object> continuation, object state, short token)
  461. {
  462. awaiter.SourceOnCompleted(continuation, state);
  463. }
  464. public UniTaskStatus UnsafeGetStatus()
  465. {
  466. return task.Status;
  467. }
  468. }
  469. sealed class DeferPromiseWithState<TState> : IUniTaskSource
  470. {
  471. Func<TState, UniTask> factory;
  472. TState argument;
  473. UniTask task;
  474. UniTask.Awaiter awaiter;
  475. public DeferPromiseWithState(TState argument, Func<TState, UniTask> factory)
  476. {
  477. this.argument = argument;
  478. this.factory = factory;
  479. }
  480. public void GetResult(short token)
  481. {
  482. awaiter.GetResult();
  483. }
  484. public UniTaskStatus GetStatus(short token)
  485. {
  486. var f = Interlocked.Exchange(ref factory, null);
  487. if (f != null)
  488. {
  489. task = f(argument);
  490. awaiter = task.GetAwaiter();
  491. }
  492. return task.Status;
  493. }
  494. public void OnCompleted(Action<object> continuation, object state, short token)
  495. {
  496. awaiter.SourceOnCompleted(continuation, state);
  497. }
  498. public UniTaskStatus UnsafeGetStatus()
  499. {
  500. return task.Status;
  501. }
  502. }
  503. sealed class DeferPromiseWithState<TState, TResult> : IUniTaskSource<TResult>
  504. {
  505. Func<TState, UniTask<TResult>> factory;
  506. TState argument;
  507. UniTask<TResult> task;
  508. UniTask<TResult>.Awaiter awaiter;
  509. public DeferPromiseWithState(TState argument, Func<TState, UniTask<TResult>> factory)
  510. {
  511. this.argument = argument;
  512. this.factory = factory;
  513. }
  514. public TResult GetResult(short token)
  515. {
  516. return awaiter.GetResult();
  517. }
  518. void IUniTaskSource.GetResult(short token)
  519. {
  520. awaiter.GetResult();
  521. }
  522. public UniTaskStatus GetStatus(short token)
  523. {
  524. var f = Interlocked.Exchange(ref factory, null);
  525. if (f != null)
  526. {
  527. task = f(argument);
  528. awaiter = task.GetAwaiter();
  529. }
  530. return task.Status;
  531. }
  532. public void OnCompleted(Action<object> continuation, object state, short token)
  533. {
  534. awaiter.SourceOnCompleted(continuation, state);
  535. }
  536. public UniTaskStatus UnsafeGetStatus()
  537. {
  538. return task.Status;
  539. }
  540. }
  541. sealed class NeverPromise<T> : IUniTaskSource<T>
  542. {
  543. static readonly Action<object> cancellationCallback = CancellationCallback;
  544. CancellationToken cancellationToken;
  545. UniTaskCompletionSourceCore<T> core;
  546. public NeverPromise(CancellationToken cancellationToken)
  547. {
  548. this.cancellationToken = cancellationToken;
  549. if (this.cancellationToken.CanBeCanceled)
  550. {
  551. this.cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationCallback, this);
  552. }
  553. }
  554. static void CancellationCallback(object state)
  555. {
  556. var self = (NeverPromise<T>)state;
  557. self.core.TrySetCanceled(self.cancellationToken);
  558. }
  559. public T GetResult(short token)
  560. {
  561. return core.GetResult(token);
  562. }
  563. public UniTaskStatus GetStatus(short token)
  564. {
  565. return core.GetStatus(token);
  566. }
  567. public UniTaskStatus UnsafeGetStatus()
  568. {
  569. return core.UnsafeGetStatus();
  570. }
  571. public void OnCompleted(Action<object> continuation, object state, short token)
  572. {
  573. core.OnCompleted(continuation, state, token);
  574. }
  575. void IUniTaskSource.GetResult(short token)
  576. {
  577. core.GetResult(token);
  578. }
  579. }
  580. }
  581. internal static class CompletedTasks
  582. {
  583. public static readonly UniTask<AsyncUnit> AsyncUnit = UniTask.FromResult(Cysharp.Threading.Tasks.AsyncUnit.Default);
  584. public static readonly UniTask<bool> True = UniTask.FromResult(true);
  585. public static readonly UniTask<bool> False = UniTask.FromResult(false);
  586. public static readonly UniTask<int> Zero = UniTask.FromResult(0);
  587. public static readonly UniTask<int> MinusOne = UniTask.FromResult(-1);
  588. public static readonly UniTask<int> One = UniTask.FromResult(1);
  589. }
  590. }