#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6)) #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member using System.Threading; using UniRx.Async.Internal; using UnityEngine; namespace UniRx.Async.Triggers { [DisallowMultipleComponent] public class AsyncDestroyTrigger : MonoBehaviour { bool called = false; UniTaskCompletionSource promise; CancellationTokenSource cancellationTokenSource; // main cancellation object canellationTokenSourceOrQueue; // external from AddCancellationTriggerOnDestroy public CancellationToken CancellationToken { get { if (cancellationTokenSource == null) { cancellationTokenSource = new CancellationTokenSource(); } return cancellationTokenSource.Token; } } /// This function is called when the MonoBehaviour will be destroyed. void OnDestroy() { called = true; promise?.TrySetResult(); cancellationTokenSource?.Cancel(); cancellationTokenSource?.Dispose(); if (canellationTokenSourceOrQueue != null) { if (canellationTokenSourceOrQueue is CancellationTokenSource cts) { cts.Cancel(); cts.Dispose(); } else { var q = (MinimumQueue)canellationTokenSourceOrQueue; while (q.Count != 0) { var c = q.Dequeue(); c.Cancel(); c.Dispose(); } } canellationTokenSourceOrQueue = null; } } /// This function is called when the MonoBehaviour will be destroyed. public UniTask OnDestroyAsync() { if (called) return UniTask.CompletedTask; return new UniTask(promise ?? (promise = new UniTaskCompletionSource())); } /// Add Cancellation Triggers on destroy public void AddCancellationTriggerOnDestroy(CancellationTokenSource cts) { if (called) { cts.Cancel(); cts.Dispose(); } if (canellationTokenSourceOrQueue == null) { canellationTokenSourceOrQueue = cts; } else if (canellationTokenSourceOrQueue is CancellationTokenSource c) { var q = new MinimumQueue(4); q.Enqueue(c); q.Enqueue(cts); canellationTokenSourceOrQueue = q; } else { ((MinimumQueue)canellationTokenSourceOrQueue).Enqueue(cts); } } } } #endif