From 10eff95a4230f03a9c42db27a5ba7167be222cc5 Mon Sep 17 00:00:00 2001 From: neuecc Date: Mon, 25 May 2020 19:36:39 +0900 Subject: [PATCH] fix: does not work zero-allocation mechanism in release build --- .../AsyncUniTaskMethodBuilder.cs | 45 +++++++++++-------- .../AsyncUniTaskVoidMethodBuilder.cs | 8 ++-- .../CompilerServices/MoveNextRunner.cs | 37 +++++++++++++-- 3 files changed, 64 insertions(+), 26 deletions(-) diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs index 2acad7e..71debef 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskMethodBuilder.cs @@ -14,7 +14,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { // cache items. AutoResetUniTaskCompletionSource promise; - IMoveNextRunner runner; + internal IMoveNextRunner runner; // 1. Static Create method. [DebuggerHidden] @@ -50,6 +50,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices [DebuggerHidden] public void SetException(Exception exception) { + var p = promise; // after return, promise will clear so require to store local. + // runner is finished, return first. if (runner != null) { @@ -57,9 +59,9 @@ namespace Cysharp.Threading.Tasks.CompilerServices runner = null; } - if (promise != null) + if (p != null) { - promise.TrySetException(exception); + p.TrySetException(exception); } else { @@ -71,6 +73,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices [DebuggerHidden] public void SetResult() { + var p = promise; // after return, promise will clear so require to store local. + // runner is finished, return first. if (runner != null) { @@ -78,9 +82,9 @@ namespace Cysharp.Threading.Tasks.CompilerServices runner = null; } - if (promise != null) + if (p != null) { - promise.TrySetResult(); + p.TrySetResult(); } } @@ -96,7 +100,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices } if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } awaiter.OnCompleted(runner.CallMoveNext); @@ -115,10 +119,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices } if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } - awaiter.OnCompleted(runner.CallMoveNext); + awaiter.UnsafeOnCompleted(runner.CallMoveNext); } // 7. Start @@ -158,7 +162,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { // cache items. AutoResetUniTaskCompletionSource promise; - IMoveNextRunner runner; + internal IMoveNextRunner runner; T result; // 1. Static Create method. @@ -194,6 +198,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices [DebuggerHidden] public void SetException(Exception exception) { + var p = promise; // after return, promise will clear so require to store local. + // runner is finished, return first. if (runner != null) { @@ -201,13 +207,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices runner = null; } - if (promise == null) + if (p == null) { promise = AutoResetUniTaskCompletionSource.CreateFromException(exception, out _); } else { - promise.TrySetException(exception); + p.TrySetException(exception); } } @@ -215,6 +221,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices [DebuggerHidden] public void SetResult(T result) { + var p = promise; // after return, promise will clear so require to store local. + // runner is finished, return first. if (runner != null) { @@ -222,13 +230,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices runner = null; } - if (promise == null) + if (p == null) { this.result = result; - return; } - - promise.TrySetResult(result); + else + { + p.TrySetResult(result); + } } // 5. AwaitOnCompleted @@ -243,7 +252,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices } if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } awaiter.OnCompleted(runner.CallMoveNext); @@ -262,10 +271,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices } if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } - awaiter.OnCompleted(runner.CallMoveNext); + awaiter.UnsafeOnCompleted(runner.CallMoveNext); } // 7. Start diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs index 73cbabb..858bfd2 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs @@ -10,7 +10,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { public struct AsyncUniTaskVoidMethodBuilder { - IMoveNextRunner runner; + internal IMoveNextRunner runner; // 1. Static Create method. [DebuggerHidden] @@ -65,7 +65,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } awaiter.OnCompleted(runner.CallMoveNext); @@ -80,10 +80,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices { if (runner == null) { - runner = MoveNextRunner.Create(ref stateMachine); + MoveNextRunner.SetRunner(ref this, ref stateMachine); } - awaiter.OnCompleted(runner.CallMoveNext); + awaiter.UnsafeOnCompleted(runner.CallMoveNext); } // 7. Start diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs index 88dc00d..3dd5191 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/MoveNextRunner.cs @@ -29,11 +29,40 @@ namespace Cysharp.Threading.Tasks.CompilerServices callMoveNext = Run; } - public static MoveNextRunner Create(ref TStateMachine stateMachine) + public static void SetRunner(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine) { - var result = pool.TryRent() ?? new MoveNextRunner(); - result.stateMachine = stateMachine; - return result; + var result = pool.TryRent(); + if (result == null) + { + result = new MoveNextRunner(); + } + + builder.runner = result; // set runner before copied. + result.stateMachine = stateMachine; // copy struct StateMachine(in release build). + } + + public static void SetRunner(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine) + { + var result = pool.TryRent(); + if (result == null) + { + result = new MoveNextRunner(); + } + + builder.runner = result; // set runner before copied. + result.stateMachine = stateMachine; // copy struct StateMachine(in release build). + } + + public static void SetRunner(ref AsyncUniTaskVoidMethodBuilder builder, ref TStateMachine stateMachine) + { + var result = pool.TryRent(); + if (result == null) + { + result = new MoveNextRunner(); + } + + builder.runner = result; // set runner before copied. + result.stateMachine = stateMachine; // copy struct StateMachine(in release build). } [DebuggerHidden]