complete infrastructure

master
Yoshifumi Kawai 2020-04-18 05:07:59 +09:00
parent 232e2eb1f2
commit 2ccaf0a03b
20 changed files with 2325 additions and 105 deletions

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using UniRx.Async;
using UnityEngine;
using UnityEngine.Networking;
@ -12,15 +13,111 @@ public class SandboxMain : MonoBehaviour
{
public Button okButton;
public Button cancelButton;
public Text text;
CancellationTokenSource cts;
async void Start()
UniTaskCompletionSource2 ucs;
void Start()
{
UnityEngine.Debug.Log("DOWNLOAD START:" + Time.frameCount);
// Setup unobserverd tskexception handling
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
var req = await UnityWebRequest.Get(Path.Combine(Application.streamingAssetsPath, "test.txt")).SendWebRequest();
// Optional: disable ExecutionContext if you don't use AsyncLocal.
//if (!ExecutionContext.IsFlowSuppressed())
//{
// ExecutionContext.SuppressFlow();
//}
UnityEngine.Debug.Log("DOWNLOAD RESULT:" + Time.frameCount + ", " + req.downloadHandler.text);
//// Optional: disable SynchronizationContext(to boostup performance) if you completely use UniTask only
//SynchronizationContext.SetSynchronizationContext(null);
// -----
Application.logMessageReceived += Application_logMessageReceived;
ucs = new UniTaskCompletionSource2();
okButton.onClick.AddListener(UniTask.VoidUnityAction(async () =>
{
await OuterAsync(true);
}));
cancelButton.onClick.AddListener(async () =>
{
text.text = "";
ucs.SetResult();
await ucs.Task;
});
}
private void Application_logMessageReceived(string condition, string stackTrace, LogType type)
{
text.text += "\n" + condition;
}
async UniTask2 OuterAsync(bool b)
{
UnityEngine.Debug.Log("START OUTER");
await InnerAsync(b);
await InnerAsync(b);
UnityEngine.Debug.Log("END OUTER");
// throw new InvalidOperationException("NAZO ERROR!?"); // error!?
}
async UniTask2 InnerAsync(bool b)
{
if (b)
{
UnityEngine.Debug.Log("Start delay:" + Time.frameCount);
await UniTask2.DelayFrame(60);
UnityEngine.Debug.Log("End delay:" + Time.frameCount);
await UniTask2.DelayFrame(60);
UnityEngine.Debug.Log("Onemore end delay:" + Time.frameCount);
}
else
{
//UnityEngine.Debug.Log("Empty END");
}
}
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
// e.SetObserved();
// or other custom write code.
UnityEngine.Debug.LogError("Unobserved:" + e.Exception.ToString());
}
}

View File

@ -96,6 +96,7 @@ LightmapSettings:
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_UseShadowmask: 1
--- !u!196 &4
@ -168,7 +169,7 @@ MonoBehaviour:
m_GameObject: {fileID: 16537670}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
@ -202,8 +203,6 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
--- !u!114 &16537673
MonoBehaviour:
m_ObjectHideFlags: 0
@ -213,7 +212,7 @@ MonoBehaviour:
m_GameObject: {fileID: 16537670}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
@ -222,8 +221,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
@ -233,6 +230,7 @@ MonoBehaviour:
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &16537674
CanvasRenderer:
m_ObjectHideFlags: 0
@ -282,6 +280,7 @@ MonoBehaviour:
m_EditorClassIdentifier:
okButton: {fileID: 16537672}
cancelButton: {fileID: 628393011}
text: {fileID: 2101290655}
--- !u!20 &519420031
Camera:
m_ObjectHideFlags: 0
@ -387,7 +386,7 @@ MonoBehaviour:
m_GameObject: {fileID: 628393009}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1392445389, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Navigation:
@ -421,8 +420,6 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.Button+ButtonClickedEvent, UnityEngine.UI, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=null
--- !u!114 &628393012
MonoBehaviour:
m_ObjectHideFlags: 0
@ -432,7 +429,7 @@ MonoBehaviour:
m_GameObject: {fileID: 628393009}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -765806418, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
@ -441,8 +438,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_Sprite: {fileID: 10905, guid: 0000000000000000f000000000000000, type: 0}
m_Type: 1
m_PreserveAspect: 0
@ -452,6 +447,7 @@ MonoBehaviour:
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!222 &628393013
CanvasRenderer:
m_ObjectHideFlags: 0
@ -506,7 +502,7 @@ MonoBehaviour:
m_GameObject: {fileID: 865871444}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
@ -515,8 +511,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
@ -566,7 +560,7 @@ MonoBehaviour:
m_GameObject: {fileID: 872009839}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1077351063, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 4f231c4fb786f3946a6b90b886c48677, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
@ -585,7 +579,7 @@ MonoBehaviour:
m_GameObject: {fileID: 872009839}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -619905303, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
@ -633,7 +627,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1556045504}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: dc42784cf147c0c48a680349fa168899, type: 3}
m_Name:
m_EditorClassIdentifier:
m_IgnoreReversedGraphics: 1
@ -650,7 +644,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1556045504}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3}
m_Name:
m_EditorClassIdentifier:
m_UiScaleMode: 0
@ -697,6 +691,7 @@ RectTransform:
m_Children:
- {fileID: 16537671}
- {fileID: 628393010}
- {fileID: 2101290654}
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
@ -751,7 +746,7 @@ MonoBehaviour:
m_GameObject: {fileID: 1584557231}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3}
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
@ -760,8 +755,6 @@ MonoBehaviour:
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
@ -786,3 +779,80 @@ CanvasRenderer:
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1584557231}
m_CullTransparentMesh: 0
--- !u!1 &2101290653
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2101290654}
- component: {fileID: 2101290656}
- component: {fileID: 2101290655}
m_Layer: 0
m_Name: Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2101290654
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 1556045508}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 1.5, y: -61.4}
m_SizeDelta: {x: 588.7, y: 398.7}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &2101290655
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f7201a12d95ffc409449d95f23cf332, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1}
m_RaycastTarget: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_FontData:
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_FontSize: 14
m_FontStyle: 0
m_BestFit: 0
m_MinSize: 10
m_MaxSize: 40
m_Alignment: 0
m_AlignByGeometry: 0
m_RichText: 1
m_HorizontalOverflow: 0
m_VerticalOverflow: 0
m_LineSpacing: 1
m_Text: New Text
--- !u!222 &2101290656
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2101290653}
m_CullTransparentMesh: 0

View File

@ -5,10 +5,12 @@
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security;
namespace UniRx.Async.CompilerServices
{
// TODO:Remove
public struct AsyncUniTaskMethodBuilder
{
UniTaskCompletionSource promise;
@ -138,7 +140,7 @@ namespace UniRx.Async.CompilerServices
}
}
// TODO:Remove
public struct AsyncUniTaskMethodBuilder<T>
{
T result;
@ -269,6 +271,247 @@ namespace UniRx.Async.CompilerServices
{
}
}
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTask2MethodBuilder
{
// cache items.
AutoResetUniTaskCompletionSource promise;
IMoveNextRunner runner;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTask2MethodBuilder Create()
{
return default;
}
// 2. TaskLike Task property.
public UniTask2 Task
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource.Create();
}
return promise.Task;
}
}
// 3. SetException
[DebuggerHidden]
public void SetException(Exception exception)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource.Create();
}
promise.SetException(exception);
}
// 4. SetResult
[DebuggerHidden]
public void SetResult()
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource.Create();
}
promise.SetResult();
}
// 5. AwaitOnCompleted
[DebuggerHidden]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource.Create();
}
if (runner == null)
{
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.OnCompleted(runner.CallMoveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource.Create();
}
if (runner == null)
{
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.OnCompleted(runner.CallMoveNext);
}
// 7. Start
[DebuggerHidden]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
}
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTask2MethodBuilder<T>
{
// cache items.
AutoResetUniTaskCompletionSource<T> promise;
IMoveNextRunner runner;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTask2MethodBuilder<T> Create()
{
return default;
}
// 2. TaskLike Task property.
[DebuggerHidden]
public UniTask2<T> Task
{
get
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
}
return promise.Task;
}
}
// 3. SetException
[DebuggerHidden]
public void SetException(Exception exception)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
}
promise.SetException(exception);
}
// 4. SetResult
[DebuggerHidden]
public void SetResult(T result)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
}
promise.SetResult(result);
}
// 5. AwaitOnCompleted
[DebuggerHidden]
public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
}
if (runner == null)
{
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.OnCompleted(runner.CallMoveNext);
}
// 6. AwaitUnsafeOnCompleted
[DebuggerHidden]
[SecuritySafeCritical]
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (promise == null)
{
promise = AutoResetUniTaskCompletionSource<T>.Create();
}
if (runner == null)
{
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.OnCompleted(runner.CallMoveNext);
}
// 7. Start
[DebuggerHidden]
public void Start<TStateMachine>(ref TStateMachine stateMachine)
where TStateMachine : IAsyncStateMachine
{
stateMachine.MoveNext();
}
// 8. SetStateMachine
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
}
}
#endif

View File

@ -11,23 +11,38 @@ namespace UniRx.Async.CompilerServices
{
public struct AsyncUniTaskVoidMethodBuilder
{
Action moveNext;
IMoveNextRunner runner;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskVoidMethodBuilder Create()
{
var builder = new AsyncUniTaskVoidMethodBuilder();
return builder;
return default;
}
// 2. TaskLike Task property(void)
public UniTaskVoid Task => default(UniTaskVoid);
public UniTaskVoid Task
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return default;
}
}
// 3. SetException
[DebuggerHidden]
public void SetException(Exception exception)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
UniTaskScheduler.PublishUnobservedTaskException(exception);
}
@ -35,7 +50,12 @@ namespace UniRx.Async.CompilerServices
[DebuggerHidden]
public void SetResult()
{
// do nothing
// runner is finished, return.
if (runner != null)
{
runner.Return();
runner = null;
}
}
// 5. AwaitOnCompleted
@ -44,14 +64,12 @@ namespace UniRx.Async.CompilerServices
where TAwaiter : INotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (moveNext == null)
if (runner == null)
{
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.OnCompleted(moveNext);
awaiter.OnCompleted(runner.CallMoveNext);
}
// 6. AwaitUnsafeOnCompleted
@ -61,14 +79,12 @@ namespace UniRx.Async.CompilerServices
where TAwaiter : ICriticalNotifyCompletion
where TStateMachine : IAsyncStateMachine
{
if (moveNext == null)
if (runner == null)
{
var runner = new MoveNextRunner<TStateMachine>();
moveNext = runner.Run;
runner.StateMachine = stateMachine; // set after create delegate.
runner = MoveNextRunner2<TStateMachine>.Create(ref stateMachine);
}
awaiter.UnsafeOnCompleted(moveNext);
awaiter.OnCompleted(runner.CallMoveNext);
}
// 7. Start
@ -83,6 +99,7 @@ namespace UniRx.Async.CompilerServices
[DebuggerHidden]
public void SetStateMachine(IAsyncStateMachine stateMachine)
{
// don't use boxed stateMachine.
}
}
}

View File

@ -2,11 +2,14 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using UniRx.Async.Internal;
namespace UniRx.Async.CompilerServices
{
// TODO: Remove it.
internal class MoveNextRunner<TStateMachine>
where TStateMachine : IAsyncStateMachine
{
@ -18,6 +21,52 @@ namespace UniRx.Async.CompilerServices
StateMachine.MoveNext();
}
}
internal interface IMoveNextRunner
{
Action CallMoveNext { get; }
void Return();
}
internal class MoveNextRunner2<TStateMachine> : IMoveNextRunner, IPromisePoolItem
where TStateMachine : IAsyncStateMachine
{
static PromisePool<MoveNextRunner2<TStateMachine>> pool = new PromisePool<MoveNextRunner2<TStateMachine>>();
TStateMachine stateMachine;
internal readonly Action callMoveNext;
public Action CallMoveNext => callMoveNext;
MoveNextRunner2()
{
callMoveNext = MoveNext;
}
public static MoveNextRunner2<TStateMachine> Create(ref TStateMachine stateMachine)
{
var result = pool.TryRent() ?? new MoveNextRunner2<TStateMachine>();
result.stateMachine = stateMachine;
return result;
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void MoveNext()
{
stateMachine.MoveNext();
}
public void Return()
{
pool.TryReturn(this);
}
void IPromisePoolItem.Reset()
{
stateMachine = default;
}
}
}
#endif

View File

@ -13,9 +13,11 @@ using System.Security;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using UnityEngine;
namespace UniRx.Async
{
// TODO: Internal.
public static class DiagnosticsExtensions
{
static bool displayFilenames = true;
@ -45,36 +47,6 @@ namespace UniRx.Async
{ typeof(UniTaskVoid), "UniTaskVoid" }
};
public static string ToStringWithCleanupAsyncStackTrace(this Exception exception)
{
if (exception == null) return "";
String message = exception.Message;
String s;
if (message == null || message.Length <= 0)
{
s = exception.GetType().ToString();
}
else
{
s = exception.GetType().ToString() + ": " + message;
}
if (exception.InnerException != null)
{
s = s + " ---> " + exception.InnerException.ToString() + Environment.NewLine + " Exception_EndOfInnerExceptionStack";
}
string stackTrace = new StackTrace(exception).CleanupAsyncStackTrace();
if (stackTrace != null)
{
s += Environment.NewLine + stackTrace;
}
return s;
}
public static string CleanupAsyncStackTrace(this StackTrace stackTrace)
{
if (stackTrace == null) return "";
@ -143,7 +115,7 @@ namespace UniRx.Async
if (fileName != null)
{
sb.Append(' ');
sb.AppendFormat(CultureInfo.InvariantCulture, "in {0}:{1}", SimplifyPath(fileName), sf.GetFileLineNumber());
sb.AppendFormat(CultureInfo.InvariantCulture, "(at {0})", AppendHyperLink(fileName, sf.GetFileLineNumber().ToString()));
}
}
@ -212,7 +184,7 @@ namespace UniRx.Async
{
return "(" + string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true))) + ")";
}
if (!t.IsGenericType) return shortName ? t.Name : t.FullName ?? t.Name;
if (!t.IsGenericType) return shortName ? t.Name : t.FullName.Replace("UniRx.Async.Triggers.", "").Replace("UniRx.Async.Internal.", "").Replace("UniRx.Async.", "") ?? t.Name;
var innerFormat = string.Join(", ", t.GetGenericArguments().Select(x => BeautifyType(x, true)));
@ -222,7 +194,7 @@ namespace UniRx.Async
genericType = "Task";
}
return typeBeautifyRegex.Replace(genericType, "") + "<" + innerFormat + ">";
return typeBeautifyRegex.Replace(genericType, "").Replace("UniRx.Async.Triggers.", "").Replace("UniRx.Async.Internal.", "").Replace("UniRx.Async.", "") + "<" + innerFormat + ">";
}
static bool IgnoreLine(MethodBase methodInfo)
@ -248,11 +220,19 @@ namespace UniRx.Async
{
return true;
}
else if (declareType.StartsWith("UniRx.Async.UniTaskCompletionSourceCore"))
{
return true;
}
else if (declareType.StartsWith("UniRx.Async.AwaiterActions"))
{
return true;
}
return false;
}
static string SimplifyPath(string path)
static string AppendHyperLink(string path, string line)
{
var fi = new FileInfo(path);
if (fi.Directory == null)
@ -261,7 +241,9 @@ namespace UniRx.Async
}
else
{
return fi.Directory.Name + "/" + fi.Name;
var fname = fi.FullName.Replace(Path.DirectorySeparatorChar, '/').Replace(Application.dataPath, "");
var withAssetsPath = "Assets/" + fname;
return "<a href=\"" + withAssetsPath + "\" line=\"" + line + "\">" + withAssetsPath + ":" + line + "</a>";
}
}
}

View File

@ -10,11 +10,14 @@ using System;
using UnityEditor.IMGUI.Controls;
using UniRx.Async.Internal;
using System.Text;
using System.Text.RegularExpressions;
namespace UniRx.Async.Editor
{
public class UniTaskTrackerViewItem : TreeViewItem
{
static Regex removeHref = new Regex("<a href.+>(.+)</a>", RegexOptions.Compiled);
public string TaskType { get; set; }
public string Elapsed { get; set; }
public string Status { get; set; }
@ -43,7 +46,8 @@ namespace UniRx.Async.Editor
}
sb.Append(str[i]);
}
return sb.ToString();
return removeHref.Replace(sb.ToString(), "$1");
}
public UniTaskTrackerViewItem(int id) : base(id)
@ -128,7 +132,7 @@ namespace UniRx.Async.Editor
var children = new List<TreeViewItem>();
TaskTracker.ForEachActiveTask((trackingId, awaiterType, status, created, stackTrace) =>
TaskTracker2.ForEachActiveTask((trackingId, awaiterType, status, created, stackTrace) =>
{
children.Add(new UniTaskTrackerViewItem(trackingId) { TaskType = awaiterType, Status = status.ToString(), Elapsed = (DateTime.UtcNow - created).TotalSeconds.ToString("00.00"), Position = stackTrace });
});

View File

@ -12,6 +12,7 @@ using UniRx.Async.Internal;
namespace UniRx.Async.Editor
{
// TODO:Remove
public class UniTaskTrackerWindow : EditorWindow
{
static int interval;
@ -206,6 +207,202 @@ namespace UniRx.Async.Editor
#endregion
}
public class UniTaskTrackerWindow2 : EditorWindow
{
static int interval;
static UniTaskTrackerWindow2 window;
// TODO:Remove 2
[MenuItem("Window/UniTask Tracker 2")]
public static void OpenWindow()
{
if (window != null)
{
window.Close();
}
// will called OnEnable(singleton instance will be set).
GetWindow<UniTaskTrackerWindow2>("UniTask Tracker").Show();
}
static readonly GUILayoutOption[] EmptyLayoutOption = new GUILayoutOption[0];
UniTaskTrackerTreeView treeView;
object splitterState;
void OnEnable()
{
window = this; // set singleton.
splitterState = SplitterGUILayout.CreateSplitterState(new float[] { 75f, 25f }, new int[] { 32, 32 }, null);
treeView = new UniTaskTrackerTreeView();
TaskTracker2.EditorEnableState.EnableAutoReload = EditorPrefs.GetBool(TaskTracker2.EnableAutoReloadKey, false);
TaskTracker2.EditorEnableState.EnableTracking = EditorPrefs.GetBool(TaskTracker2.EnableTrackingKey, false);
TaskTracker2.EditorEnableState.EnableStackTrace = EditorPrefs.GetBool(TaskTracker2.EnableStackTraceKey, false);
}
void OnGUI()
{
// Head
RenderHeadPanel();
// Splittable
SplitterGUILayout.BeginVerticalSplit(this.splitterState, EmptyLayoutOption);
{
// Column Tabble
RenderTable();
// StackTrace details
RenderDetailsPanel();
}
SplitterGUILayout.EndVerticalSplit();
}
#region HeadPanel
public static bool EnableAutoReload => TaskTracker2.EditorEnableState.EnableAutoReload;
public static bool EnableTracking => TaskTracker2.EditorEnableState.EnableTracking;
public static bool EnableStackTrace => TaskTracker2.EditorEnableState.EnableStackTrace;
static readonly GUIContent EnableAutoReloadHeadContent = EditorGUIUtility.TrTextContent("Enable AutoReload", "Reload automatically.", (Texture)null);
static readonly GUIContent ReloadHeadContent = EditorGUIUtility.TrTextContent("Reload", "Reload View.", (Texture)null);
static readonly GUIContent GCHeadContent = EditorGUIUtility.TrTextContent("GC.Collect", "Invoke GC.Collect.", (Texture)null);
static readonly GUIContent EnableTrackingHeadContent = EditorGUIUtility.TrTextContent("Enable Tracking", "Start to track async/await UniTask. Performance impact: low", (Texture)null);
static readonly GUIContent EnableStackTraceHeadContent = EditorGUIUtility.TrTextContent("Enable StackTrace", "Capture StackTrace when task is started. Performance impact: high", (Texture)null);
// [Enable Tracking] | [Enable StackTrace]
void RenderHeadPanel()
{
EditorGUILayout.BeginVertical(EmptyLayoutOption);
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar, EmptyLayoutOption);
if (GUILayout.Toggle(EnableAutoReload, EnableAutoReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableAutoReload)
{
TaskTracker2.EditorEnableState.EnableAutoReload = !EnableAutoReload;
}
if (GUILayout.Toggle(EnableTracking, EnableTrackingHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableTracking)
{
TaskTracker2.EditorEnableState.EnableTracking = !EnableTracking;
}
if (GUILayout.Toggle(EnableStackTrace, EnableStackTraceHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption) != EnableStackTrace)
{
TaskTracker2.EditorEnableState.EnableStackTrace = !EnableStackTrace;
}
GUILayout.FlexibleSpace();
if (GUILayout.Button(ReloadHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
{
TaskTracker2.CheckAndResetDirty();
treeView.ReloadAndSort();
Repaint();
}
if (GUILayout.Button(GCHeadContent, EditorStyles.toolbarButton, EmptyLayoutOption))
{
GC.Collect(0);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
}
#endregion
#region TableColumn
Vector2 tableScroll;
GUIStyle tableListStyle;
void RenderTable()
{
if (tableListStyle == null)
{
tableListStyle = new GUIStyle("CN Box");
tableListStyle.margin.top = 0;
tableListStyle.padding.left = 3;
}
EditorGUILayout.BeginVertical(tableListStyle, EmptyLayoutOption);
this.tableScroll = EditorGUILayout.BeginScrollView(this.tableScroll, new GUILayoutOption[]
{
GUILayout.ExpandWidth(true),
GUILayout.MaxWidth(2000f)
});
var controlRect = EditorGUILayout.GetControlRect(new GUILayoutOption[]
{
GUILayout.ExpandHeight(true),
GUILayout.ExpandWidth(true)
});
treeView?.OnGUI(controlRect);
EditorGUILayout.EndScrollView();
EditorGUILayout.EndVertical();
}
private void Update()
{
if (EnableAutoReload)
{
if (interval++ % 120 == 0)
{
if (TaskTracker2.CheckAndResetDirty())
{
treeView.ReloadAndSort();
Repaint();
}
}
}
}
#endregion
#region Details
static GUIStyle detailsStyle;
Vector2 detailsScroll;
void RenderDetailsPanel()
{
if (detailsStyle == null)
{
detailsStyle = new GUIStyle("CN Message");
detailsStyle.wordWrap = false;
detailsStyle.stretchHeight = true;
detailsStyle.margin.right = 15;
}
string message = "";
var selected = treeView.state.selectedIDs;
if (selected.Count > 0)
{
var first = selected[0];
var item = treeView.CurrentBindingItems.FirstOrDefault(x => x.id == first) as UniTaskTrackerViewItem;
if (item != null)
{
message = item.Position;
}
}
detailsScroll = EditorGUILayout.BeginScrollView(this.detailsScroll, EmptyLayoutOption);
var vector = detailsStyle.CalcSize(new GUIContent(message));
EditorGUILayout.SelectableLabel(message, detailsStyle, new GUILayoutOption[]
{
GUILayout.ExpandHeight(true),
GUILayout.ExpandWidth(true),
GUILayout.MinWidth(vector.x),
GUILayout.MinHeight(vector.y)
});
EditorGUILayout.EndScrollView();
}
#endregion
}
}
#endif

View File

@ -1,10 +1,13 @@
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591
using System;
using System.Runtime.CompilerServices;
namespace UniRx.Async
{
// TODO:rename to UniTaskStatus
public enum AwaiterStatus
{
/// <summary>The operation has not yet completed.</summary>
@ -17,6 +20,24 @@ namespace UniRx.Async
Canceled = 3
}
// similar as IValueTaskSource
public interface IUniTaskSource
{
AwaiterStatus GetStatus(short token);
void OnCompleted(Action<object> continuation, object state, short token);
void GetResult(short token);
AwaiterStatus UnsafeGetStatus(); // only for debug use.
}
public interface IUniTaskSource<out T> : IUniTaskSource
{
new T GetResult(short token);
}
public interface IAwaiter : ICriticalNotifyCompletion
{
AwaiterStatus Status { get; }

View File

@ -0,0 +1,53 @@
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;
using System.Threading;
namespace UniRx.Async.Internal
{
internal interface IPromisePoolItem
{
void Reset();
}
internal class PromisePool<T>
where T : class, IPromisePoolItem
{
int count = 0;
readonly ConcurrentQueue<T> queue = new ConcurrentQueue<T>();
readonly int maxSize;
public PromisePool(int maxSize = 256)
{
this.maxSize = maxSize;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T TryRent()
{
if (queue.TryDequeue(out var value))
{
Interlocked.Decrement(ref count);
return value;
}
return null;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryReturn(T value)
{
value.Reset(); // reset when return.
if (count < maxSize)
{
queue.Enqueue(value);
Interlocked.Increment(ref count);
return true;
}
else
{
return false;
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fcb1f7467a3e2b64c8a016c8aee2f9b4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,6 +10,7 @@ namespace UniRx.Async.Internal
{
// public for add user custom.
// TODO: Remove
public static class TaskTracker
{
#if UNITY_EDITOR
@ -147,6 +148,123 @@ namespace UniRx.Async.Internal
}
}
}
public static class TaskTracker2
{
#if UNITY_EDITOR
static int trackingId = 0;
public const string EnableAutoReloadKey = "UniTaskTrackerWindow_EnableAutoReloadKey";
public const string EnableTrackingKey = "UniTaskTrackerWindow_EnableTrackingKey";
public const string EnableStackTraceKey = "UniTaskTrackerWindow_EnableStackTraceKey";
public static class EditorEnableState
{
static bool enableAutoReload;
public static bool EnableAutoReload
{
get { return enableAutoReload; }
set
{
enableAutoReload = value;
UnityEditor.EditorPrefs.SetBool(EnableAutoReloadKey, value);
}
}
static bool enableTracking;
public static bool EnableTracking
{
get { return enableTracking; }
set
{
enableTracking = value;
UnityEditor.EditorPrefs.SetBool(EnableTrackingKey, value);
}
}
static bool enableStackTrace;
public static bool EnableStackTrace
{
get { return enableStackTrace; }
set
{
enableStackTrace = value;
UnityEditor.EditorPrefs.SetBool(EnableStackTraceKey, value);
}
}
}
#endif
static List<KeyValuePair<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>> listPool = new List<KeyValuePair<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>>();
static readonly WeakDictionary<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)> tracking = new WeakDictionary<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>();
[Conditional("UNITY_EDITOR")]
public static void TrackActiveTask(IUniTaskSource task, int skipFrame)
{
#if UNITY_EDITOR
dirty = true;
if (!EditorEnableState.EnableTracking) return;
var stackTrace = EditorEnableState.EnableStackTrace ? new StackTrace(skipFrame, true).CleanupAsyncStackTrace() : "";
tracking.TryAdd(task, (Interlocked.Increment(ref trackingId), DateTime.UtcNow, stackTrace));
#endif
}
[Conditional("UNITY_EDITOR")]
public static void RemoveTracking(IUniTaskSource task)
{
#if UNITY_EDITOR
dirty = true;
if (!EditorEnableState.EnableTracking) return;
var success = tracking.TryRemove(task);
#endif
}
static bool dirty;
public static bool CheckAndResetDirty()
{
var current = dirty;
dirty = false;
return current;
}
/// <summary>(trackingId, awaiterType, awaiterStatus, createdTime, stackTrace)</summary>
public static void ForEachActiveTask(Action<int, string, AwaiterStatus, DateTime, string> action)
{
lock (listPool)
{
var count = tracking.ToList(ref listPool, clear: false);
try
{
for (int i = 0; i < count; i++)
{
string typeName = null;
var keyType = listPool[i].Key.GetType();
if (keyType.IsNested)
{
typeName = keyType.DeclaringType.Name + "." + keyType.Name;
}
else
{
typeName = keyType.Name;
}
action(listPool[i].Value.trackingId, typeName, listPool[i].Key.UnsafeGetStatus(), listPool[i].Value.addTime, listPool[i].Value.stackTrace);
listPool[i] = new KeyValuePair<IUniTaskSource, (int trackingId, DateTime addTime, string stackTrace)>(null, (0, default(DateTime), null)); // clear
}
}
catch
{
listPool.Clear();
throw;
}
}
}
}
}
#endif

View File

@ -3,6 +3,7 @@
using System;
using System.Threading;
using UnityEngine.Events;
namespace UniRx.Async
{
@ -86,6 +87,16 @@ namespace UniRx.Async
asyncAction().Forget();
}
public static Action VoidAction(Func<UniTask> asyncAction)
{
return () => Void(asyncAction);
}
public static UnityAction VoidUnityAction(Func<UniTask> asyncAction)
{
return () => Void(asyncAction);
}
/// <summary>
/// helper of create add UniTaskVoid to delegate.
/// For example: FooEvent += (sender, e) => UniTask.Void(async arg => { /* */ }, (sender, e))

View File

@ -3,14 +3,628 @@
#pragma warning disable CS0436
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Sources;
using UniRx.Async.CompilerServices;
using UniRx.Async.Internal;
namespace UniRx.Async
{
public partial struct UniTask2
{
public static UniTask2 DelayFrame(int frameCount, PlayerLoopTiming timing = PlayerLoopTiming.Update, CancellationToken cancellationToken = default)
{
return new UniTask2(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token);
//return new ValueTask<int>(DelayPromiseCore2.Create(frameCount, timing, cancellationToken, out var token), token);
}
}
public class DelayPromiseCore2 : IUniTaskSource, IPlayerLoopItem, IPromisePoolItem
{
static readonly PromisePool<DelayPromiseCore2> pool = new PromisePool<DelayPromiseCore2>();
int delayFrameCount;
CancellationToken cancellationToken;
int currentFrameCount;
UniTaskCompletionSourceCore<object> core;
DelayPromiseCore2()
{
}
public static IUniTaskSource Create(int delayFrameCount, PlayerLoopTiming timing, CancellationToken cancellationToken, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource.CreateFromCanceled(cancellationToken, out token);
}
var result = pool.TryRent() ?? new DelayPromiseCore2();
result.delayFrameCount = delayFrameCount;
result.cancellationToken = cancellationToken;
TaskTracker2.TrackActiveTask(result, 3);
PlayerLoopHelper.AddAction(timing, result);
token = result.core.Version;
return result;
}
public void GetResult(short token)
{
try
{
core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public bool MoveNext()
{
if (cancellationToken.IsCancellationRequested)
{
TaskTracker2.RemoveTracking(this);
core.SetCancellation(cancellationToken);
return false;
}
if (currentFrameCount == delayFrameCount)
{
TaskTracker2.RemoveTracking(this);
core.SetResult(null);
return false;
}
currentFrameCount++;
return true;
}
public void Reset()
{
core.Reset();
currentFrameCount = default;
delayFrameCount = default;
cancellationToken = default;
}
}
/// <summary>
/// Lightweight unity specified task-like object.
/// </summary>
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2
public partial struct UniTask2
{
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
readonly IUniTaskSource awaiter;
readonly short token;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UniTask2(IUniTaskSource awaiter, short token)
{
this.awaiter = awaiter;
this.token = token;
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return awaiter.GetStatus(token);
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Awaiter GetAwaiter()
{
return new Awaiter(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void GetResult()
{
awaiter.GetResult(token);
}
// TODO:can be suppress?
///// <summary>
///// returns (bool IsCanceled) instead of throws OperationCanceledException.
///// </summary>
//public UniTask<bool> SuppressCancellationThrow()
//{
// var status = Status;
// if (status == AwaiterStatus.Succeeded) return CompletedTasks.False;
// if (status == AwaiterStatus.Canceled) return CompletedTasks.True;
// //return new UniTask<bool>(new IsCanceledAwaiter(awaiter));
//}
public override string ToString()
{
var status = this.awaiter.UnsafeGetStatus();
return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")";
}
//public static implicit operator UniTask<AsyncUnit>(UniTask2 task)
//{
// // TODO:
// throw new NotImplementedException();
// //if (task.awaiter != null)
// //{
// // if (task.awaiter.IsCompleted)
// // {
// // return DefaultAsyncUnitTask;
// // }
// // else
// // {
// // // UniTask<T> -> UniTask is free but UniTask -> UniTask<T> requires wrapping cost.
// // return new UniTask<AsyncUnit>(new AsyncUnitAwaiter(task.awaiter));
// // }
// //}
// //else
// //{
// // return DefaultAsyncUnitTask;
// //}
//}
//class AsyncUnitAwaiter : IAwaiter<AsyncUnit>
//{
// readonly IAwaiter2 awaiter;
// public AsyncUnitAwaiter(IAwaiter2 awaiter)
// {
// this.awaiter = awaiter;
// }
// public bool IsCompleted => awaiter.IsCompleted;
// public AwaiterStatus Status => awaiter.Status;
// public AsyncUnit GetResult()
// {
// awaiter.GetResult();
// return AsyncUnit.Default;
// }
// public void OnCompleted(Action continuation)
// {
// awaiter.OnCompleted(continuation);
// }
// public void UnsafeOnCompleted(Action continuation)
// {
// awaiter.UnsafeOnCompleted(continuation);
// }
// void IAwaiter.GetResult()
// {
// awaiter.GetResult();
// }
//}
class IsCanceledAwaiter : IUniTaskSource
{
readonly IUniTaskSource awaiter;
public IsCanceledAwaiter(IUniTaskSource awaiter)
{
this.awaiter = awaiter;
}
//public bool IsCompleted => awaiter.IsCompleted;
//public AwaiterStatus Status => awaiter.Status;
//public bool GetResult()
//{
// if (awaiter.Status == AwaiterStatus.Canceled)
// {
// return true;
// }
// awaiter.GetResult();
// return false;
//}
//public void OnCompleted(Action continuation)
//{
// awaiter.OnCompleted(continuation);
//}
//public void UnsafeOnCompleted(Action continuation)
//{
// awaiter.UnsafeOnCompleted(continuation);
//}
//void IAwaiter.GetResult()
//{
// awaiter.GetResult();
//}
public void GetResult(short token)
{
// TODO: bool
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
{
//return true;
}
awaiter.GetResult(token);
// return false
throw new NotImplementedException();
}
public AwaiterStatus GetStatus(short token)
{
return awaiter.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return awaiter.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
awaiter.OnCompleted(continuation, state, token);
}
}
public readonly struct Awaiter : ICriticalNotifyCompletion
{
readonly UniTask2 task;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Awaiter(in UniTask2 task)
{
this.task = task;
}
public bool IsCompleted
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status.IsCompleted();
}
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status;
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void GetResult()
{
task.GetResult();
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnsafeOnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
}
internal static class AwaiterActions
{
internal static readonly Action<object> InvokeActionDelegate = InvokeAction;
static void InvokeAction(object state)
{
((Action)state).Invoke();
}
}
/// <summary>
/// Lightweight unity specified task-like object.
/// </summary>
[AsyncMethodBuilder(typeof(AsyncUniTask2MethodBuilder))] // TODO:AsyncUniTask2~T
public struct UniTask2<T>
{
// static readonly UniTask<AsyncUnit> DefaultAsyncUnitTask = new UniTask<AsyncUnit>(AsyncUnit.Default);
readonly IUniTaskSource<T> awaiter;
readonly short token;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public UniTask2(IUniTaskSource<T> awaiter, short token)
{
this.awaiter = awaiter;
this.token = token;
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return awaiter.GetStatus(token);
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Awaiter GetAwaiter()
{
return new Awaiter(this);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
T GetResult()
{
return awaiter.GetResult(token);
}
// TODO:can be suppress?
///// <summary>
///// returns (bool IsCanceled) instead of throws OperationCanceledException.
///// </summary>
//public UniTask<bool> SuppressCancellationThrow()
//{
// var status = Status;
// if (status == AwaiterStatus.Succeeded) return CompletedTasks.False;
// if (status == AwaiterStatus.Canceled) return CompletedTasks.True;
// //return new UniTask<bool>(new IsCanceledAwaiter(awaiter));
//}
public override string ToString()
{
var status = this.awaiter.UnsafeGetStatus();
return (status == AwaiterStatus.Succeeded) ? "()" : "(" + status + ")";
}
//public static implicit operator UniTask<AsyncUnit>(UniTask2 task)
//{
// // TODO:
// throw new NotImplementedException();
// //if (task.awaiter != null)
// //{
// // if (task.awaiter.IsCompleted)
// // {
// // return DefaultAsyncUnitTask;
// // }
// // else
// // {
// // // UniTask<T> -> UniTask is free but UniTask -> UniTask<T> requires wrapping cost.
// // return new UniTask<AsyncUnit>(new AsyncUnitAwaiter(task.awaiter));
// // }
// //}
// //else
// //{
// // return DefaultAsyncUnitTask;
// //}
//}
//class AsyncUnitAwaiter : IAwaiter<AsyncUnit>
//{
// readonly IAwaiter2 awaiter;
// public AsyncUnitAwaiter(IAwaiter2 awaiter)
// {
// this.awaiter = awaiter;
// }
// public bool IsCompleted => awaiter.IsCompleted;
// public AwaiterStatus Status => awaiter.Status;
// public AsyncUnit GetResult()
// {
// awaiter.GetResult();
// return AsyncUnit.Default;
// }
// public void OnCompleted(Action continuation)
// {
// awaiter.OnCompleted(continuation);
// }
// public void UnsafeOnCompleted(Action continuation)
// {
// awaiter.UnsafeOnCompleted(continuation);
// }
// void IAwaiter.GetResult()
// {
// awaiter.GetResult();
// }
//}
class IsCanceledAwaiter : IUniTaskSource
{
readonly IUniTaskSource awaiter;
public IsCanceledAwaiter(IUniTaskSource awaiter)
{
this.awaiter = awaiter;
}
//public bool IsCompleted => awaiter.IsCompleted;
//public AwaiterStatus Status => awaiter.Status;
//public bool GetResult()
//{
// if (awaiter.Status == AwaiterStatus.Canceled)
// {
// return true;
// }
// awaiter.GetResult();
// return false;
//}
//public void OnCompleted(Action continuation)
//{
// awaiter.OnCompleted(continuation);
//}
//public void UnsafeOnCompleted(Action continuation)
//{
// awaiter.UnsafeOnCompleted(continuation);
//}
//void IAwaiter.GetResult()
//{
// awaiter.GetResult();
//}
public void GetResult(short token)
{
// TODO: bool
if (awaiter.GetStatus(token) == AwaiterStatus.Canceled)
{
//return true;
}
awaiter.GetResult(token);
// return false
throw new NotImplementedException();
}
public AwaiterStatus GetStatus(short token)
{
return awaiter.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return awaiter.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
awaiter.OnCompleted(continuation, state, token);
}
}
public readonly struct Awaiter : ICriticalNotifyCompletion
{
readonly UniTask2<T> task;
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Awaiter(in UniTask2<T> task)
{
this.task = task;
}
public bool IsCompleted
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status.IsCompleted();
}
}
public AwaiterStatus Status
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
return task.Status;
}
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public T GetResult()
{
return task.GetResult();
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void UnsafeOnCompleted(Action continuation)
{
task.awaiter.OnCompleted(AwaiterActions.InvokeActionDelegate, continuation, task.token);
}
}
}
/// <summary>
/// Lightweight unity specified task-like object.
/// </summary>

View File

@ -6,11 +6,14 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Threading;
using UniRx.Async.Internal;
namespace UniRx.Async
{
// TODO: Remove all?
internal class ExceptionHolder
{
ExceptionDispatchInfo exception;
@ -408,6 +411,587 @@ namespace UniRx.Async
((ICriticalNotifyCompletion)this).UnsafeOnCompleted(continuation);
}
}
[StructLayout(LayoutKind.Auto)]
public struct UniTaskCompletionSourceCore<TResult>
{
// Struct Size: TResult + (8 + 2 + 1 + 1 + 8 + 8)
TResult result;
object error; // Exception or OperationCanceledException
short version;
bool completed;
bool hasUnhandledError;
Action<object> continuation;
object continuationState;
public void Reset()
{
ReportUnhandledError();
unchecked
{
version += 1; // incr version.
}
completed = false;
result = default;
error = null;
hasUnhandledError = false;
continuation = null;
continuationState = null;
}
void ReportUnhandledError()
{
if (hasUnhandledError)
{
try
{
if (error is OperationCanceledException oc)
{
UniTaskScheduler.PublishUnobservedTaskException(oc);
}
else if (error is ExceptionDispatchInfo ei)
{
UniTaskScheduler.PublishUnobservedTaskException(ei.SourceException);
}
}
catch
{
}
}
}
/// <summary>Completes with a successful result.</summary>
/// <param name="result">The result.</param>
public void SetResult(TResult result)
{
this.result = result;
SignalCompletion();
}
/// <summary>Completes with an error.</summary>
/// <param name="error">The exception.</param>
public void SetException(Exception error)
{
this.hasUnhandledError = true;
this.error = ExceptionDispatchInfo.Capture(error);
SignalCompletion();
}
public void SetCancellation(CancellationToken cancellationToken)
{
this.error = new OperationCanceledException(cancellationToken);
SignalCompletion();
}
/// <summary>Gets the operation version.</summary>
public short Version => version;
/// <summary>Gets the status of the operation.</summary>
/// <param name="token">Opaque value that was provided to the <see cref="UniTask"/>'s constructor.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AwaiterStatus GetStatus(short token)
{
ValidateToken(token);
return (continuation == null || !completed) ? AwaiterStatus.Pending
: (error == null) ? AwaiterStatus.Succeeded
: (error is OperationCanceledException) ? AwaiterStatus.Canceled
: AwaiterStatus.Faulted;
}
/// <summary>Gets the status of the operation without token validation.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AwaiterStatus UnsafeGetStatus()
{
return (continuation == null || !completed) ? AwaiterStatus.Pending
: (error == null) ? AwaiterStatus.Succeeded
: (error is OperationCanceledException) ? AwaiterStatus.Canceled
: AwaiterStatus.Faulted;
}
/// <summary>Gets the result of the operation.</summary>
/// <param name="token">Opaque value that was provided to the <see cref="UniTask"/>'s constructor.</param>
// [StackTraceHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TResult GetResult(short token)
{
ValidateToken(token);
if (!completed)
{
throw new InvalidOperationException("not yet completed.");
}
if (error != null)
{
hasUnhandledError = false;
if (error is OperationCanceledException oce)
{
throw oce;
}
else if (error is ExceptionDispatchInfo edi)
{
edi.Throw();
}
throw new InvalidOperationException("Critical: invalid exception type was held.");
}
return result;
}
/// <summary>Schedules the continuation action for this operation.</summary>
/// <param name="continuation">The continuation to invoke when the operation has completed.</param>
/// <param name="state">The state object to pass to <paramref name="continuation"/> when it's invoked.</param>
/// <param name="token">Opaque value that was provided to the <see cref="UniTask"/>'s constructor.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void OnCompleted(Action<object> continuation, object state, short token /*, ValueTaskSourceOnCompletedFlags flags */)
{
if (continuation == null)
{
throw new ArgumentNullException(nameof(continuation));
}
ValidateToken(token);
/* no use ValueTaskSourceOnCOmpletedFlags, always no capture ExecutionContext and SynchronizationContext. */
object oldContinuation = this.continuation;
if (oldContinuation == null)
{
continuationState = state;
oldContinuation = Interlocked.CompareExchange(ref this.continuation, continuation, null);
}
if (oldContinuation != null)
{
// Operation already completed, so we need to queue the supplied callback.
if (!ReferenceEquals(oldContinuation, UniTaskCompletionSourceCoreShared.s_sentinel))
{
throw new InvalidOperationException("already completed.");
}
continuation(state);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void ValidateToken(short token)
{
if (token != version)
{
throw new InvalidOperationException("token version is not matched.");
}
}
/// <summary>Signals that the operation has completed. Invoked after the result or error has been set.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private void SignalCompletion()
{
if (completed)
{
throw new InvalidOperationException();
}
completed = true;
if (continuation != null || Interlocked.CompareExchange(ref this.continuation, UniTaskCompletionSourceCoreShared.s_sentinel, null) != null)
{
continuation(continuationState);
}
}
}
public class UniTaskCompletionSource2 : IUniTaskSource
{
UniTaskCompletionSourceCore<AsyncUnit> core;
bool handled = false;
public UniTaskCompletionSource2()
{
TaskTracker2.TrackActiveTask(this, 2);
}
[Conditional("UNITY_EDITOR")]
void MarkHandled()
{
if (!handled)
{
handled = true;
TaskTracker2.RemoveTracking(this);
}
}
public UniTask2 Task
{
get
{
return new UniTask2(this, core.Version);
}
}
public void Reset()
{
// Reset, re-active tracker
handled = false;
TaskTracker2.TrackActiveTask(this, 2);
core.Reset();
}
public void SetResult()
{
core.SetResult(AsyncUnit.Default);
}
public void SetCancellation(CancellationToken cancellationToken)
{
core.SetCancellation(cancellationToken);
}
public void SetException(Exception exception)
{
core.SetException(exception);
}
public void GetResult(short token)
{
MarkHandled();
core.GetResult(token);
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
~UniTaskCompletionSource2()
{
// clear error information.
core.Reset();
}
}
public class AutoResetUniTaskCompletionSource : IUniTaskSource, IPromisePoolItem
{
static readonly PromisePool<AutoResetUniTaskCompletionSource> pool = new PromisePool<AutoResetUniTaskCompletionSource>();
UniTaskCompletionSourceCore<AsyncUnit> core;
AutoResetUniTaskCompletionSource()
{
}
public static AutoResetUniTaskCompletionSource Create()
{
// TODO:Add TaskTracker
return pool.TryRent() ?? new AutoResetUniTaskCompletionSource();
}
public static AutoResetUniTaskCompletionSource CreateFromCanceled(CancellationToken cancellationToken, out short token)
{
var source = Create();
source.SetCancellation(cancellationToken);
token = source.core.Version;
return source;
}
public static AutoResetUniTaskCompletionSource CreateFromException(Exception exception, out short token)
{
var source = Create();
source.SetException(exception);
token = source.core.Version;
return source;
}
public static AutoResetUniTaskCompletionSource CreateCompleted(out short token)
{
var source = Create();
source.SetResult();
token = source.core.Version;
return source;
}
public UniTask2 Task
{
get
{
return new UniTask2(this, core.Version);
}
}
public void SetResult()
{
core.SetResult(AsyncUnit.Default);
}
public void SetCancellation(CancellationToken cancellationToken)
{
core.SetCancellation(cancellationToken);
}
public void SetException(Exception exception)
{
core.SetException(exception);
}
public void GetResult(short token)
{
try
{
// TODO:Remove TaskTracker
core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
void IPromisePoolItem.Reset()
{
core.Reset();
}
~AutoResetUniTaskCompletionSource()
{
if (pool.TryReturn(this))
{
GC.ReRegisterForFinalize(this);
return;
}
}
}
public class UniTaskCompletionSource2<T> : IUniTaskSource<T>
{
UniTaskCompletionSourceCore<T> core;
bool handled = false;
public UniTaskCompletionSource2()
{
// TODO: TaskTracker.TrackActiveTask
}
[Conditional("UNITY_EDITOR")]
void MarkHandled()
{
if (!handled)
{
handled = true;
// TODO:
// TaskTracker.RemoveTracking(this);
}
}
public UniTask2<T> Task
{
get
{
return new UniTask2<T>(this, core.Version);
}
}
public void Reset()
{
// TODO:Reset, reactive tracker: TaskTracker.TrackActiveTask
handled = false;
core.Reset();
}
public void SetResult(T result)
{
core.SetResult(result);
}
public void SetCancellation(CancellationToken cancellationToken)
{
core.SetCancellation(cancellationToken);
}
public void SetException(Exception exception)
{
core.SetException(exception);
}
public T GetResult(short token)
{
MarkHandled();
return core.GetResult(token);
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
~UniTaskCompletionSource2()
{
// clear error information.
core.Reset();
}
}
public class AutoResetUniTaskCompletionSource<T> : IUniTaskSource<T>, IPromisePoolItem
{
static readonly PromisePool<AutoResetUniTaskCompletionSource<T>> pool = new PromisePool<AutoResetUniTaskCompletionSource<T>>();
UniTaskCompletionSourceCore<T> core;
AutoResetUniTaskCompletionSource()
{
}
public static AutoResetUniTaskCompletionSource<T> Create()
{
// TODO:Add TaskTracker
return pool.TryRent() ?? new AutoResetUniTaskCompletionSource<T>();
}
public static AutoResetUniTaskCompletionSource<T> CreateFromCanceled(CancellationToken cancellationToken, out short token)
{
var source = Create();
source.SetCancellation(cancellationToken);
token = source.core.Version;
return source;
}
public static AutoResetUniTaskCompletionSource<T> CreateFromException(Exception exception, out short token)
{
var source = Create();
source.SetException(exception);
token = source.core.Version;
return source;
}
public static AutoResetUniTaskCompletionSource<T> CreateFromResult(T result, out short token)
{
var source = Create();
source.SetResult(result);
token = source.core.Version;
return source;
}
public UniTask2<T> Task
{
get
{
return new UniTask2<T>(this, core.Version);
}
}
public void SetResult(T result)
{
core.SetResult(result);
}
public void SetCancellation(CancellationToken cancellationToken)
{
core.SetCancellation(cancellationToken);
}
public void SetException(Exception exception)
{
core.SetException(exception);
}
public T GetResult(short token)
{
try
{
// TODO:Remove TaskTracker
return core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
void IPromisePoolItem.Reset()
{
core.Reset();
}
~AutoResetUniTaskCompletionSource()
{
if (pool.TryReturn(this))
{
GC.ReRegisterForFinalize(this);
return;
}
}
}
internal static class UniTaskCompletionSourceCoreShared // separated out of generic to avoid unnecessary duplication
{
internal static readonly Action<object> s_sentinel = CompletionSentinel;
private static void CompletionSentinel(object _) // named method to aid debugging
{
throw new InvalidOperationException("The sentinel delegate should never be invoked.");
}
}
}
#endif

View File

@ -19,12 +19,12 @@ namespace UniRx.Async
public static bool PropagateOperationCanceledException = false;
/// <summary>
/// Write log type when catch unobserved exception and not registered UnobservedTaskException. Default is Warning.
/// Write log type when catch unobserved exception and not registered UnobservedTaskException. Default is Error.
/// </summary>
public static UnityEngine.LogType UnobservedExceptionWriteLogType = UnityEngine.LogType.Warning;
public static UnityEngine.LogType UnobservedExceptionWriteLogType = UnityEngine.LogType.Error;
/// <summary>
/// Dispatch exception event to Unity MainThread.
/// Dispatch exception event to Unity MainThread. Default is true.
/// </summary>
public static bool DispatchUnityMainThread = true;
@ -42,7 +42,7 @@ namespace UniRx.Async
if (UnobservedTaskException != null)
{
if (Thread.CurrentThread.ManagedThreadId == PlayerLoopHelper.MainThreadId)
if (!DispatchUnityMainThread || Thread.CurrentThread.ManagedThreadId == PlayerLoopHelper.MainThreadId)
{
// allows inlining call.
UnobservedTaskException.Invoke(ex);

View File

@ -491,6 +491,127 @@ namespace UniRx.Async
}
}
// TODO: try to check API.
class ResourceRequestConfiguredSource : IUniTaskSource<UnityEngine.Object>, IPlayerLoopItem, IPromisePoolItem
{
static readonly PromisePool<ResourceRequestConfiguredSource> pool = new PromisePool<ResourceRequestConfiguredSource>();
ResourceRequest asyncOperation;
IProgress<float> progress;
CancellationToken cancellationToken;
UniTaskCompletionSourceCore<UnityEngine.Object> core;
ResourceRequestConfiguredSource()
{
}
public static IUniTaskSource<UnityEngine.Object> Create(ResourceRequest asyncOperation, PlayerLoopTiming timing, IProgress<float> progress, CancellationToken cancellationToken, out short token)
{
if (cancellationToken.IsCancellationRequested)
{
return AutoResetUniTaskCompletionSource<UnityEngine.Object>.CreateFromCanceled(cancellationToken, out token);
}
var result = pool.TryRent() ?? new ResourceRequestConfiguredSource();
result.asyncOperation = asyncOperation;
result.progress = progress;
result.cancellationToken = cancellationToken;
#if UNITY_EDITOR
// TODO:capture???
//var capturedStackTraceForDebugging = TaskTracker.CaptureStackTrace(2);
// TODO:Add ActiveTask?
// TaskTracker.TrackActiveTask(
#endif
PlayerLoopHelper.AddAction(timing, result);
token = result.core.Version;
return result;
}
public UnityEngine.Object GetResult(short token)
{
try
{
return core.GetResult(token);
}
finally
{
pool.TryReturn(this);
}
}
void IUniTaskSource.GetResult(short token)
{
GetResult(token);
}
public AwaiterStatus GetStatus(short token)
{
return core.GetStatus(token);
}
public AwaiterStatus UnsafeGetStatus()
{
return core.UnsafeGetStatus();
}
public void OnCompleted(Action<object> continuation, object state, short token)
{
core.OnCompleted(continuation, state, token);
}
public bool MoveNext()
{
if (cancellationToken.IsCancellationRequested)
{
// TODO:Remove Tracking
// TaskTracker.RemoveTracking();
core.SetCancellation(cancellationToken);
return false;
}
if (progress != null)
{
progress.Report(asyncOperation.progress);
}
if (asyncOperation.isDone)
{
// TODO:Remove Tracking
// TaskTracker.RemoveTracking();
core.SetResult(asyncOperation.asset);
return false;
}
return true;
}
public void Reset()
{
core.Reset();
asyncOperation = default;
progress = default;
cancellationToken = default;
}
}
public struct AssetBundleRequestAwaiter : IAwaiter<UnityEngine.Object>
{
AssetBundleRequest asyncOperation;

View File

@ -8,7 +8,7 @@ EditorBuildSettings:
- enabled: 1
path: Assets/Scenes/SandboxMain.unity
guid: 2cda990e2423bbf4892e6590ba056729
- enabled: 1
path: Assets/Scenes/NextScene.unity
guid: dfced9d8875377c44a1d53620d36f0d5
- enabled: 0
path:
guid: 00000000000000000000000000000000
m_configObjects: {}

View File

@ -3,7 +3,7 @@
--- !u!129 &1
PlayerSettings:
m_ObjectHideFlags: 0
serializedVersion: 17
serializedVersion: 20
productGUID: 904cd7a3163037f42a9204c0e2f2b7bd
AndroidProfiler: 0
AndroidFilterTouchesWhenObscured: 0
@ -52,8 +52,7 @@ PlayerSettings:
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
iosShowActivityIndicatorOnLoading: -1
androidShowActivityIndicatorOnLoading: -1
iosAppInBackgroundBehavior: 0
displayResolutionDialog: 0
iosUseCustomAppBackgroundBehavior: 0
iosAllowHTTPDownload: 1
allowedAutorotateToPortrait: 1
allowedAutorotateToPortraitUpsideDown: 1
@ -80,11 +79,11 @@ PlayerSettings:
usePlayerLog: 1
bakeCollisionMeshes: 0
forceSingleInstance: 0
useFlipModelSwapchain: 1
resizableWindow: 1
useMacAppStoreValidation: 0
macAppStoreCategory: public.app-category.games
gpuSkinning: 0
graphicsJobs: 0
xboxPIXTextureCapture: 0
xboxEnableAvatar: 0
xboxEnableKinect: 0
@ -92,7 +91,6 @@ PlayerSettings:
xboxEnableFitness: 0
visibleInBackground: 1
allowFullscreenSwitch: 1
graphicsJobMode: 0
fullscreenMode: 3
xboxSpeechDB: 0
xboxEnableHeadOrientation: 0
@ -105,6 +103,7 @@ PlayerSettings:
xboxOneMonoLoggingLevel: 0
xboxOneLoggingLevel: 1
xboxOneDisableEsram: 0
xboxOneEnableTypeOptimization: 0
xboxOnePresentImmediateThreshold: 0
switchQueueCommandMemory: 0
switchQueueControlMemory: 16384
@ -112,6 +111,7 @@ PlayerSettings:
switchNVNShaderPoolsGranularity: 33554432
switchNVNDefaultPoolsGranularity: 16777216
switchNVNOtherPoolsGranularity: 16777216
vulkanNumSwapchainBuffers: 3
vulkanEnableSetSRGBWrite: 0
m_SupportedAspectRatios:
4:3: 1
@ -150,11 +150,13 @@ PlayerSettings:
sharedDepthBuffer: 1
dashSupport: 1
lowOverheadMode: 0
protectedContext: 0
v2Signing: 1
enable360StereoCapture: 0
isWsaHolographicRemotingEnabled: 0
protectGraphicsMemory: 0
enableFrameTimingStats: 0
useHDRDisplay: 0
D3DHDRBitDepth: 0
m_ColorGamuts: 00000000
targetPixelDensity: 30
resolutionScalingMode: 0
@ -164,7 +166,7 @@ PlayerSettings:
Standalone: com.Company.ProductName
buildNumber: {}
AndroidBundleVersionCode: 1
AndroidMinSdkVersion: 16
AndroidMinSdkVersion: 19
AndroidTargetSdkVersion: 0
AndroidPreferredInstallLocation: 1
aotOptions:
@ -179,10 +181,10 @@ PlayerSettings:
StripUnusedMeshComponents: 1
VertexChannelCompressionMask: 4054
iPhoneSdkVersion: 988
iOSTargetOSVersionString: 9.0
iOSTargetOSVersionString: 10.0
tvOSSdkVersion: 0
tvOSRequireExtendedGameController: 0
tvOSTargetOSVersionString: 9.0
tvOSTargetOSVersionString: 10.0
uIPrerenderedIcon: 0
uIRequiresPersistentWiFi: 0
uIRequiresFullScreen: 1
@ -272,16 +274,46 @@ PlayerSettings:
androidGamepadSupportLevel: 0
AndroidValidateAppBundleSize: 1
AndroidAppBundleSizeToValidate: 100
resolutionDialogBanner: {fileID: 0}
m_BuildTargetIcons: []
m_BuildTargetPlatformIcons: []
m_BuildTargetBatching: []
m_BuildTargetGraphicsJobs:
- m_BuildTarget: MacStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: Switch
m_GraphicsJobs: 0
- m_BuildTarget: MetroSupport
m_GraphicsJobs: 0
- m_BuildTarget: AppleTVSupport
m_GraphicsJobs: 0
- m_BuildTarget: BJMSupport
m_GraphicsJobs: 0
- m_BuildTarget: LinuxStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: PS4Player
m_GraphicsJobs: 0
- m_BuildTarget: iOSSupport
m_GraphicsJobs: 0
- m_BuildTarget: WindowsStandaloneSupport
m_GraphicsJobs: 0
- m_BuildTarget: XboxOnePlayer
m_GraphicsJobs: 0
- m_BuildTarget: LuminSupport
m_GraphicsJobs: 0
- m_BuildTarget: AndroidPlayer
m_GraphicsJobs: 0
- m_BuildTarget: WebGLSupport
m_GraphicsJobs: 0
m_BuildTargetGraphicsJobMode:
- m_BuildTarget: PS4Player
m_GraphicsJobMode: 0
- m_BuildTarget: XboxOnePlayer
m_GraphicsJobMode: 0
m_BuildTargetGraphicsAPIs:
- m_BuildTarget: AndroidPlayer
m_APIs: 150000000b000000
m_Automatic: 0
m_BuildTargetVRSettings: []
m_BuildTargetEnableVuforiaSettings: []
openGLRequireES31: 0
openGLRequireES31AEP: 0
openGLRequireES32: 0
@ -400,6 +432,7 @@ PlayerSettings:
switchRatingsInt_9: 0
switchRatingsInt_10: 0
switchRatingsInt_11: 0
switchRatingsInt_12: 0
switchLocalCommunicationIds_0:
switchLocalCommunicationIds_1:
switchLocalCommunicationIds_2:
@ -481,6 +514,7 @@ PlayerSettings:
ps4UseResolutionFallback: 0
ps4ReprojectionSupport: 0
ps4UseAudio3dBackend: 0
ps4UseLowGarlicFragmentationMode: 1
ps4SocialScreenEnabled: 0
ps4ScriptOptimizationLevel: 0
ps4Audio3dVirtualSpeakerCount: 14
@ -499,6 +533,7 @@ PlayerSettings:
ps4contentSearchFeaturesUsed: 0
ps4attribEyeToEyeDistanceSettingVR: 0
ps4IncludedModules: []
ps4attribVROutputEnabled: 0
monoEnv:
splashScreenBackgroundSourceLandscape: {fileID: 0}
splashScreenBackgroundSourcePortrait: {fileID: 0}
@ -602,13 +637,6 @@ PlayerSettings:
luminVersion:
m_VersionCode: 1
m_VersionName:
facebookSdkVersion: 7.9.4
facebookAppId:
facebookCookies: 1
facebookLogging: 1
facebookStatus: 1
facebookXfbml: 0
facebookFrictionlessRequests: 1
apiCompatibilityLevel: 6
cloudProjectId:
framebufferDepthMemorylessMode: 0

View File

@ -4,7 +4,7 @@
UnityConnectSettings:
m_ObjectHideFlags: 0
serializedVersion: 1
m_Enabled: 1
m_Enabled: 0
m_TestMode: 0
m_EventOldUrl: https://api.uca.cloud.unity3d.com/v1/events
m_EventUrl: https://cdp.cloud.unity3d.com/v1/events