|
- #pragma warning disable CS1591
-
- using Cysharp.Threading.Tasks.Internal;
- using System;
- using System.Linq;
- using System.Diagnostics;
- using System.Runtime.CompilerServices;
-
- namespace Cysharp.Threading.Tasks.CompilerServices
- {
- // #ENABLE_IL2CPP in this file is to avoid bug of IL2CPP VM.
- // Issue is tracked on https://issuetracker.unity3d.com/issues/il2cpp-incorrect-results-when-calling-a-method-from-outside-class-in-a-struct
- // but currently it is labeled `Won't Fix`.
-
- internal interface IStateMachineRunner
- {
- Action MoveNext { get; }
- void Return();
-
- #if ENABLE_IL2CPP
- Action ReturnAction { get; }
- #endif
- }
-
- internal interface IStateMachineRunnerPromise : IUniTaskSource
- {
- Action MoveNext { get; }
- UniTask Task { get; }
- void SetResult();
- void SetException(Exception exception);
- }
-
- internal interface IStateMachineRunnerPromise<T> : IUniTaskSource<T>
- {
- Action MoveNext { get; }
- UniTask<T> Task { get; }
- void SetResult(T result);
- void SetException(Exception exception);
- }
-
- internal static class StateMachineUtility
- {
- // Get AsyncStateMachine internal state to check IL2CPP bug
- public static int GetState(IAsyncStateMachine stateMachine)
- {
- var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
- .First(x => x.Name.EndsWith("__state"));
- return (int)info.GetValue(stateMachine);
- }
- }
-
- internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
- where TStateMachine : IAsyncStateMachine
- {
- static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
-
- #if ENABLE_IL2CPP
- public Action ReturnAction { get; }
- #endif
-
- TStateMachine stateMachine;
-
- public Action MoveNext { get; }
-
- public AsyncUniTaskVoid()
- {
- MoveNext = Run;
- #if ENABLE_IL2CPP
- ReturnAction = Return;
- #endif
- }
-
- public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
- {
- if (!pool.TryPop(out var result))
- {
- result = new AsyncUniTaskVoid<TStateMachine>();
- }
- TaskTracker.TrackActiveTask(result, 3);
-
- runnerFieldRef = result; // set runner before copied.
- result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
- }
-
- static AsyncUniTaskVoid()
- {
- TaskPool.RegisterSizeGetter(typeof(AsyncUniTaskVoid<TStateMachine>), () => pool.Size);
- }
-
- AsyncUniTaskVoid<TStateMachine> nextNode;
- public ref AsyncUniTaskVoid<TStateMachine> NextNode => ref nextNode;
-
- public void Return()
- {
- TaskTracker.RemoveTracking(this);
- stateMachine = default;
- pool.TryPush(this);
- }
-
- [DebuggerHidden]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- void Run()
- {
- stateMachine.MoveNext();
- }
-
- // dummy interface implementation for TaskTracker.
-
- UniTaskStatus IUniTaskSource.GetStatus(short token)
- {
- return UniTaskStatus.Pending;
- }
-
- UniTaskStatus IUniTaskSource.UnsafeGetStatus()
- {
- return UniTaskStatus.Pending;
- }
-
- void IUniTaskSource.OnCompleted(Action<object> continuation, object state, short token)
- {
- }
-
- void IUniTaskSource.GetResult(short token)
- {
- }
- }
-
- internal sealed class AsyncUniTask<TStateMachine> : IStateMachineRunnerPromise, IUniTaskSource, ITaskPoolNode<AsyncUniTask<TStateMachine>>
- where TStateMachine : IAsyncStateMachine
- {
- static TaskPool<AsyncUniTask<TStateMachine>> pool;
-
- #if ENABLE_IL2CPP
- readonly Action returnDelegate;
- #endif
- public Action MoveNext { get; }
-
- TStateMachine stateMachine;
- UniTaskCompletionSourceCore<AsyncUnit> core;
-
- AsyncUniTask()
- {
- MoveNext = Run;
- #if ENABLE_IL2CPP
- returnDelegate = Return;
- #endif
- }
-
- public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
- {
- if (!pool.TryPop(out var result))
- {
- result = new AsyncUniTask<TStateMachine>();
- }
- TaskTracker.TrackActiveTask(result, 3);
-
- runnerPromiseFieldRef = result; // set runner before copied.
- result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
- }
-
- AsyncUniTask<TStateMachine> nextNode;
- public ref AsyncUniTask<TStateMachine> NextNode => ref nextNode;
-
- static AsyncUniTask()
- {
- TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
- }
-
- void Return()
- {
- TaskTracker.RemoveTracking(this);
- core.Reset();
- stateMachine = default;
- pool.TryPush(this);
- }
-
- bool TryReturn()
- {
- TaskTracker.RemoveTracking(this);
- core.Reset();
- stateMachine = default;
- return pool.TryPush(this);
- }
-
- [DebuggerHidden]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- void Run()
- {
- stateMachine.MoveNext();
- }
-
- public UniTask Task
- {
- [DebuggerHidden]
- get
- {
- return new UniTask(this, core.Version);
- }
- }
-
- [DebuggerHidden]
- public void SetResult()
- {
- core.TrySetResult(AsyncUnit.Default);
- }
-
- [DebuggerHidden]
- public void SetException(Exception exception)
- {
- core.TrySetException(exception);
- }
-
- [DebuggerHidden]
- public void GetResult(short token)
- {
- try
- {
- core.GetResult(token);
- }
- finally
- {
- #if ENABLE_IL2CPP
- // workaround for IL2CPP bug.
- PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
- #else
- TryReturn();
- #endif
- }
- }
-
- [DebuggerHidden]
- public UniTaskStatus GetStatus(short token)
- {
- return core.GetStatus(token);
- }
-
- [DebuggerHidden]
- public UniTaskStatus UnsafeGetStatus()
- {
- return core.UnsafeGetStatus();
- }
-
- [DebuggerHidden]
- public void OnCompleted(Action<object> continuation, object state, short token)
- {
- core.OnCompleted(continuation, state, token);
- }
- }
-
- internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromise<T>, IUniTaskSource<T>, ITaskPoolNode<AsyncUniTask<TStateMachine, T>>
- where TStateMachine : IAsyncStateMachine
- {
- static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
-
- #if ENABLE_IL2CPP
- readonly Action returnDelegate;
- #endif
-
- public Action MoveNext { get; }
-
- TStateMachine stateMachine;
- UniTaskCompletionSourceCore<T> core;
-
- AsyncUniTask()
- {
- MoveNext = Run;
- #if ENABLE_IL2CPP
- returnDelegate = Return;
- #endif
- }
-
- public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
- {
- if (!pool.TryPop(out var result))
- {
- result = new AsyncUniTask<TStateMachine, T>();
- }
- TaskTracker.TrackActiveTask(result, 3);
-
- runnerPromiseFieldRef = result; // set runner before copied.
- result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
- }
-
- AsyncUniTask<TStateMachine, T> nextNode;
- public ref AsyncUniTask<TStateMachine, T> NextNode => ref nextNode;
-
- static AsyncUniTask()
- {
- TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
- }
-
- void Return()
- {
- TaskTracker.RemoveTracking(this);
- core.Reset();
- stateMachine = default;
- pool.TryPush(this);
- }
-
- bool TryReturn()
- {
- TaskTracker.RemoveTracking(this);
- core.Reset();
- stateMachine = default;
- return pool.TryPush(this);
- }
-
- [DebuggerHidden]
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- void Run()
- {
- // UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
- stateMachine.MoveNext();
- }
-
- public UniTask<T> Task
- {
- [DebuggerHidden]
- get
- {
- return new UniTask<T>(this, core.Version);
- }
- }
-
- [DebuggerHidden]
- public void SetResult(T result)
- {
- core.TrySetResult(result);
- }
-
- [DebuggerHidden]
- public void SetException(Exception exception)
- {
- core.TrySetException(exception);
- }
-
- [DebuggerHidden]
- public T GetResult(short token)
- {
- try
- {
- return core.GetResult(token);
- }
- finally
- {
- #if ENABLE_IL2CPP
- // workaround for IL2CPP bug.
- PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
- #else
- TryReturn();
- #endif
- }
- }
-
- [DebuggerHidden]
- void IUniTaskSource.GetResult(short token)
- {
- GetResult(token);
- }
-
- [DebuggerHidden]
- public UniTaskStatus GetStatus(short token)
- {
- return core.GetStatus(token);
- }
-
- [DebuggerHidden]
- public UniTaskStatus UnsafeGetStatus()
- {
- return core.UnsafeGetStatus();
- }
-
- [DebuggerHidden]
- public void OnCompleted(Action<object> continuation, object state, short token)
- {
- core.OnCompleted(continuation, state, token);
- }
- }
- }
|