< Summary

Class:DCL.Helpers.PromiseAsyncExtensions
Assembly:Promise
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Promise/PromiseAsyncExtensions.cs
Covered lines:7
Uncovered lines:1
Coverable lines:8
Total lines:132
Line coverage:87.5% (7 of 8)
Covered branches:0
Total branches:0

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
GetAwaiter[T](...)0%110100%
WithCancellation[T](...)0%110100%
ToUniTask[T](...)0%5.935066.67%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Helpers/Promise/PromiseAsyncExtensions.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using System;
 3using System.Threading;
 4
 5namespace DCL.Helpers
 6{
 7    public static class PromiseAsyncExtensions
 8    {
 9        public static UniTask<T>.Awaiter GetAwaiter<T>(this Promise<T> promise) =>
 210            promise.ToUniTask().GetAwaiter();
 11
 12        public static UniTask<T> WithCancellation<T>(this Promise<T> promise, CancellationToken cancellationToken) =>
 6513            promise.ToUniTask(cancellationToken);
 14
 15        public static UniTask<T> ToUniTask<T>(this Promise<T> promise, CancellationToken cancellationToken = default)
 16        {
 6817            if (promise == null)
 018                throw new ArgumentNullException(nameof(promise));
 19
 6820            if (cancellationToken.IsCancellationRequested) return UniTask.FromCanceled<T>(cancellationToken);
 6821            if (promise.failed) return UniTask.FromException<T>(promise.exception);
 10422            if (promise.resolved) return UniTask.FromResult(promise.value);
 23
 3224            return new UniTask<T>(PromiseCompletionSource<T>.Create(promise, cancellationToken, out short token), token)
 25        }
 26
 27        internal sealed class PromiseCompletionSource<T> : IUniTaskSource<T>, ITaskPoolNode<PromiseCompletionSource<T>>
 28        {
 29            private static TaskPool<PromiseCompletionSource<T>> pool;
 30
 31            private PromiseCompletionSource<T> nextNode;
 32
 33            public ref PromiseCompletionSource<T> NextNode => ref nextNode;
 34
 35            private Promise<T> innerPromise;
 36            private CancellationToken cancellationToken;
 37            private CancellationTokenRegistration cancellationTokenRegistration;
 38
 39            private UniTaskCompletionSourceCore<T> core;
 40
 41            static PromiseCompletionSource()
 42            {
 43                TaskPool.RegisterSizeGetter(typeof(PromiseCompletionSource<T>), () => pool.Size);
 44            }
 45
 46            private PromiseCompletionSource() { }
 47
 48            private void SetData(Promise<T> innerPromise, CancellationToken cancellationToken)
 49            {
 50                this.innerPromise = innerPromise;
 51                this.cancellationToken = cancellationToken;
 52
 53                // Subscribe directly to `Promise` instead of calling `MoveNext` to prevent skipping an extra frame
 54                innerPromise.onSuccess += SetResult;
 55                innerPromise.onError += SetException;
 56
 57                cancellationTokenRegistration = cancellationToken.RegisterWithoutCaptureExecutionContext(SetCancelled);
 58            }
 59
 60            private void SetCancelled()
 61            {
 62                UnsubscribeBeforeReset();
 63                core.TrySetCanceled(cancellationToken);
 64            }
 65
 66            private void SetResult(T result)
 67            {
 68                UnsubscribeBeforeReset();
 69                core.TrySetResult(result);
 70            }
 71
 72            private void SetException(string _)
 73            {
 74                UnsubscribeBeforeReset();
 75                core.TrySetException(innerPromise.exception);
 76            }
 77
 78            private void UnsubscribeBeforeReset()
 79            {
 80                cancellationTokenRegistration.Dispose();
 81                innerPromise.onSuccess -= SetResult;
 82                innerPromise.onError -= SetException;
 83            }
 84
 85            public static IUniTaskSource<T> Create(Promise<T> promise, CancellationToken cancellationToken, out short to
 86            {
 87                if (cancellationToken.IsCancellationRequested) { return AutoResetUniTaskCompletionSource<T>.CreateFromCa
 88
 89                if (!pool.TryPop(out var result)) result = new PromiseCompletionSource<T>();
 90
 91                result.SetData(promise, cancellationToken);
 92
 93                TaskTracker.TrackActiveTask(result, 3);
 94
 95                token = result.core.Version;
 96
 97                return result;
 98            }
 99
 100            public UniTaskStatus GetStatus(short token) =>
 101                core.GetStatus(token);
 102
 103            public void OnCompleted(Action<object> continuation, object state, short token)
 104            {
 105                core.OnCompleted(continuation, state, token);
 106            }
 107
 108            public T GetResult(short token)
 109            {
 110                try { return core.GetResult(token); }
 111                finally { TryReturn(); }
 112            }
 113
 114            void IUniTaskSource.GetResult(short token)
 115            {
 116                GetResult(token);
 117            }
 118
 119            public UniTaskStatus UnsafeGetStatus() =>
 120                core.UnsafeGetStatus();
 121
 122            private bool TryReturn()
 123            {
 124                TaskTracker.RemoveTracking(this);
 125                core.Reset();
 126                innerPromise = null;
 127                cancellationToken = default;
 128                return pool.TryPush(this);
 129            }
 130        }
 131    }
 132}