complete infrastructure

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

View File

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

View File

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

View File

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