complete infrastructure
parent
232e2eb1f2
commit
2ccaf0a03b
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
|
|
|
@ -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
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: fcb1f7467a3e2b64c8a016c8aee2f9b4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
|
@ -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))
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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: {}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue