fix: does not work zero-allocation mechanism in release build

pull/61/head
neuecc 2020-05-25 19:36:39 +09:00
parent d27d6d5d9d
commit 10eff95a42
3 changed files with 64 additions and 26 deletions

View File

@ -14,7 +14,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
// cache items. // cache items.
AutoResetUniTaskCompletionSource promise; AutoResetUniTaskCompletionSource promise;
IMoveNextRunner runner; internal IMoveNextRunner runner;
// 1. Static Create method. // 1. Static Create method.
[DebuggerHidden] [DebuggerHidden]
@ -50,6 +50,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetException(Exception exception) public void SetException(Exception exception)
{ {
var p = promise; // after return, promise will clear so require to store local.
// runner is finished, return first. // runner is finished, return first.
if (runner != null) if (runner != null)
{ {
@ -57,9 +59,9 @@ namespace Cysharp.Threading.Tasks.CompilerServices
runner = null; runner = null;
} }
if (promise != null) if (p != null)
{ {
promise.TrySetException(exception); p.TrySetException(exception);
} }
else else
{ {
@ -71,6 +73,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetResult() public void SetResult()
{ {
var p = promise; // after return, promise will clear so require to store local.
// runner is finished, return first. // runner is finished, return first.
if (runner != null) if (runner != null)
{ {
@ -78,9 +82,9 @@ namespace Cysharp.Threading.Tasks.CompilerServices
runner = null; runner = null;
} }
if (promise != null) if (p != null)
{ {
promise.TrySetResult(); p.TrySetResult();
} }
} }
@ -96,7 +100,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.OnCompleted(runner.CallMoveNext);
@ -115,10 +119,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.UnsafeOnCompleted(runner.CallMoveNext);
} }
// 7. Start // 7. Start
@ -158,7 +162,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
// cache items. // cache items.
AutoResetUniTaskCompletionSource<T> promise; AutoResetUniTaskCompletionSource<T> promise;
IMoveNextRunner runner; internal IMoveNextRunner runner;
T result; T result;
// 1. Static Create method. // 1. Static Create method.
@ -194,6 +198,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetException(Exception exception) public void SetException(Exception exception)
{ {
var p = promise; // after return, promise will clear so require to store local.
// runner is finished, return first. // runner is finished, return first.
if (runner != null) if (runner != null)
{ {
@ -201,13 +207,13 @@ namespace Cysharp.Threading.Tasks.CompilerServices
runner = null; runner = null;
} }
if (promise == null) if (p == null)
{ {
promise = AutoResetUniTaskCompletionSource<T>.CreateFromException(exception, out _); promise = AutoResetUniTaskCompletionSource<T>.CreateFromException(exception, out _);
} }
else else
{ {
promise.TrySetException(exception); p.TrySetException(exception);
} }
} }
@ -215,6 +221,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
[DebuggerHidden] [DebuggerHidden]
public void SetResult(T result) public void SetResult(T result)
{ {
var p = promise; // after return, promise will clear so require to store local.
// runner is finished, return first. // runner is finished, return first.
if (runner != null) if (runner != null)
{ {
@ -222,13 +230,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices
runner = null; runner = null;
} }
if (promise == null) if (p == null)
{ {
this.result = result; this.result = result;
return;
} }
else
promise.TrySetResult(result); {
p.TrySetResult(result);
}
} }
// 5. AwaitOnCompleted // 5. AwaitOnCompleted
@ -243,7 +252,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.OnCompleted(runner.CallMoveNext);
@ -262,10 +271,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.UnsafeOnCompleted(runner.CallMoveNext);
} }
// 7. Start // 7. Start

View File

@ -10,7 +10,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
public struct AsyncUniTaskVoidMethodBuilder public struct AsyncUniTaskVoidMethodBuilder
{ {
IMoveNextRunner runner; internal IMoveNextRunner runner;
// 1. Static Create method. // 1. Static Create method.
[DebuggerHidden] [DebuggerHidden]
@ -65,7 +65,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.OnCompleted(runner.CallMoveNext);
@ -80,10 +80,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
if (runner == null) if (runner == null)
{ {
runner = MoveNextRunner<TStateMachine>.Create(ref stateMachine); MoveNextRunner<TStateMachine>.SetRunner(ref this, ref stateMachine);
} }
awaiter.OnCompleted(runner.CallMoveNext); awaiter.UnsafeOnCompleted(runner.CallMoveNext);
} }
// 7. Start // 7. Start

View File

@ -29,11 +29,40 @@ namespace Cysharp.Threading.Tasks.CompilerServices
callMoveNext = Run; callMoveNext = Run;
} }
public static MoveNextRunner<TStateMachine> Create(ref TStateMachine stateMachine) public static void SetRunner(ref AsyncUniTaskMethodBuilder builder, ref TStateMachine stateMachine)
{ {
var result = pool.TryRent() ?? new MoveNextRunner<TStateMachine>(); var result = pool.TryRent();
result.stateMachine = stateMachine; if (result == null)
return result; {
result = new MoveNextRunner<TStateMachine>();
}
builder.runner = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
}
public static void SetRunner<T>(ref AsyncUniTaskMethodBuilder<T> builder, ref TStateMachine stateMachine)
{
var result = pool.TryRent();
if (result == null)
{
result = new MoveNextRunner<TStateMachine>();
}
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<TStateMachine>();
}
builder.runner = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
} }
[DebuggerHidden] [DebuggerHidden]