Skip to content

Commit

Permalink
Merge branch 'fix-il2cpp'
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed Jun 9, 2020
2 parents 7289fe6 + 3c0aa03 commit 80704e4
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 24 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,8 @@ foreach (var (type, size) in TaskPool.GetCacheSizeInfo())
}
```

> In UnityEditor profiler shows allocation of compiler generated AsyncStateMachine but it only occurs in debug(development) build. C# Compiler generate AsyncStateMachine as class on Debug build and as struct on Release build. And also currently due to IL2CPP limitation, in IL2CPP build, UniTask do boxing AsyncStateMachine when needed so sometimes exists `one` allocation.
API References
---
UniTask's API References is hosted at [cysharp.github.io/UniTask](https://cysharp.github.io/UniTask/api/Cysharp.Threading.Tasks.html) by [DocFX](https://dotnet.github.io/docfx/) and [Cysharp/DocfXTemplate](https://github.com/Cysharp/DocfxTemplate).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder
{
internal IStateMachineRunnerPromise runnerPromise;
IStateMachineRunnerPromise runnerPromise;
Exception ex;

// 1. Static Create method.
Expand Down Expand Up @@ -80,7 +80,7 @@ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
}

awaiter.OnCompleted(runnerPromise.MoveNext);
Expand All @@ -96,7 +96,7 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTask<TStateMachine>.SetStateMachine(ref stateMachine, ref runnerPromise);
}

awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
Expand Down Expand Up @@ -138,7 +138,7 @@ private object ObjectIdForDebugger
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder<T>
{
internal IStateMachineRunnerPromise<T> runnerPromise;
IStateMachineRunnerPromise<T> runnerPromise;
Exception ex;
T result;

Expand Down Expand Up @@ -211,7 +211,7 @@ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
}

awaiter.OnCompleted(runnerPromise.MoveNext);
Expand All @@ -227,7 +227,7 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter
{
if (runnerPromise == null)
{
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTask<TStateMachine, T>.SetStateMachine(ref stateMachine, ref runnerPromise);
}

awaiter.UnsafeOnCompleted(runnerPromise.MoveNext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskVoidMethodBuilder
{
internal IStateMachineRunner runner;
IStateMachineRunner runner;

// 1. Static Create method.
[DebuggerHidden]
Expand Down Expand Up @@ -70,7 +70,7 @@ public void AwaitOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref
{
if (runner == null)
{
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
}

awaiter.OnCompleted(runner.MoveNext);
Expand All @@ -86,7 +86,7 @@ public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>(ref TAwaiter awaiter
{
if (runner == null)
{
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref this, ref stateMachine);
AsyncUniTaskVoid<TStateMachine>.SetStateMachine(ref stateMachine, ref runner);
}

awaiter.UnsafeOnCompleted(runner.MoveNext);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using Cysharp.Threading.Tasks.Internal;
using System;
using System.Linq;
using System.Diagnostics;
using System.Runtime.CompilerServices;

Expand Down Expand Up @@ -29,12 +30,26 @@ internal interface IStateMachineRunnerPromise<T> : IUniTaskSource<T>
void SetException(Exception exception);
}

internal static class StateMachineUtility
{
public static int GetState(IAsyncStateMachine stateMachine)
{
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.First(x => x.Name.EndsWith("__state"));
return (int)info.GetValue(stateMachine);
}
}

internal sealed class AsyncUniTaskVoid<TStateMachine> : IStateMachineRunner, ITaskPoolNode<AsyncUniTaskVoid<TStateMachine>>, IUniTaskSource
where TStateMachine : IAsyncStateMachine
{
static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;

#if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
#else
TStateMachine stateMachine;
#endif

public Action MoveNext { get; }

Expand All @@ -43,15 +58,15 @@ public AsyncUniTaskVoid()
MoveNext = Run;
}

public static void SetStateMachine(ref AsyncUniTaskVoidMethodBuilder builder, ref TStateMachine stateMachine)
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTaskVoid<TStateMachine>();
}
TaskTracker.TrackActiveTask(result, 3);

builder.runner = result; // set runner before copied.
runnerFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}

Expand Down Expand Up @@ -102,7 +117,11 @@ internal sealed class AsyncUniTask<TStateMachine> : IStateMachineRunnerPromise,
{
static TaskPool<AsyncUniTask<TStateMachine>> pool;

#if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
#else
TStateMachine stateMachine;
#endif

public Action MoveNext { get; }

Expand All @@ -113,15 +132,15 @@ internal sealed class AsyncUniTask<TStateMachine> : IStateMachineRunnerPromise,
MoveNext = Run;
}

public static void SetStateMachine(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine)
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTask<TStateMachine>();
}
TaskTracker.TrackActiveTask(result, 3);

builder.runnerPromise = result; // set runner before copied.
runnerPromiseFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}

Expand Down Expand Up @@ -213,7 +232,11 @@ internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromis
{
static TaskPool<AsyncUniTask<TStateMachine, T>> pool;

#if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue.
#else
TStateMachine stateMachine;
#endif

public Action MoveNext { get; }

Expand All @@ -224,18 +247,21 @@ internal sealed class AsyncUniTask<TStateMachine, T> : IStateMachineRunnerPromis
MoveNext = Run;
}

public static void SetStateMachine(ref AsyncUniTaskMethodBuilder<T> builder, ref TStateMachine stateMachine)
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
{
if (!pool.TryPop(out var result))
{
result = new AsyncUniTask<TStateMachine, T>();
}
TaskTracker.TrackActiveTask(result, 3);

builder.runnerPromise = result; // set runner before copied.
runnerPromiseFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).

// UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine));
}


public AsyncUniTask<TStateMachine, T> NextNode { get; set; }

static AsyncUniTask()
Expand All @@ -255,6 +281,7 @@ bool TryReturn()
[MethodImpl(MethodImplOptions.AggressiveInlining)]
void Run()
{
// UnityEngine.Debug.Log($"MoveNext State:" + StateMachineUtility.GetState(stateMachine));
stateMachine.MoveNext();
}

Expand Down
2 changes: 2 additions & 0 deletions src/UniTask/Assets/Plugins/UniTask/Runtime/Linq/ToArray.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ internal static class ToArray
{
internal static async UniTask<TSource[]> ToArrayAsync<TSource>(IUniTaskAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
{
// UnityEngine.Debug.Log("Called ToArray");

var pool = ArrayPool<TSource>.Shared;
var array = pool.Rent(16);

Expand Down
2 changes: 1 addition & 1 deletion src/UniTask/Assets/Plugins/UniTask/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "com.cysharp.unitask",
"displayName": "UniTask",
"version": "2.0.14",
"version": "2.0.15",
"unity": "2018.4",
"description": "Provides an efficient async/await integration to Unity.",
"keywords": [ "async/await", "async", "Task", "UniTask" ],
Expand Down
25 changes: 17 additions & 8 deletions src/UniTask/Assets/Scenes/SandboxMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,19 @@ async UniTask DelayCheck()
Debug.Log("after");
}

private async UniTaskVoid ExecuteAsync()
{
Debug.Log("1");
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
Debug.Log("------------------");
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
Debug.Log("2");
}
}


void Start()
{
Expand All @@ -423,7 +436,7 @@ void Start()

//StartCoroutine(TestCoroutine().ToCoroutine());

Application.logMessageReceived += Application_logMessageReceived;
// Application.logMessageReceived += Application_logMessageReceived;



Expand All @@ -432,13 +445,9 @@ void Start()

okButton.onClick.AddListener(UniTask.UnityAction(async () =>
{
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
Debug.Log("------------------");
{
var xs = await UniTaskAsyncEnumerable.TimerFrame(1).ToArrayAsync();
}
_ = ExecuteAsync();

await UniTask.Yield();

//await DelayCheck();
/*
Expand Down

0 comments on commit 80704e4

Please sign in to comment.