UniTask/Assets/UniRx.Async/CompilerServices/AsyncUniTaskMethodBuilder.cs

273 lines
7.5 KiB
C#
Raw Normal View History

2019-05-19 23:14:47 +08:00
#if CSHARP_7_OR_LATER || (UNITY_2018_3_OR_NEWER && (NET_STANDARD_2_0 || NET_4_6))
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
2020-04-18 04:07:59 +08:00
using System.Runtime.InteropServices;
2019-05-19 23:14:47 +08:00
using System.Security;
namespace UniRx.Async.CompilerServices
{
2020-04-18 04:07:59 +08:00
[StructLayout(LayoutKind.Auto)]
public struct AsyncUniTaskMethodBuilder
2020-04-18 04:07:59 +08:00
{
// cache items.
AutoResetUniTaskCompletionSource promise;
IMoveNextRunner runner;
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder Create()
2020-04-18 04:07:59 +08:00
{
return default;
}
// 2. TaskLike Task property.
public UniTask Task
2020-04-18 04:07:59 +08:00
{
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
2020-04-18 21:11:40 +08:00
if (promise != null)
{
return promise.Task;
}
if (runner == null)
2020-04-18 04:07:59 +08:00
{
return UniTask.CompletedTask;
2020-04-18 04:07:59 +08:00
}
2020-04-18 21:11:40 +08:00
promise = AutoResetUniTaskCompletionSource.Create();
2020-04-18 04:07:59 +08:00
return promise.Task;
}
}
// 3. SetException
[DebuggerHidden]
public void SetException(Exception exception)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
2020-04-18 21:11:40 +08:00
if (promise != null)
2020-04-18 04:07:59 +08:00
{
2020-04-26 01:38:16 +08:00
promise.TrySetException(exception);
2020-04-18 21:11:40 +08:00
}
else
{
promise = AutoResetUniTaskCompletionSource.CreateFromException(exception, out _);
2020-04-18 04:07:59 +08:00
}
}
// 4. SetResult
[DebuggerHidden]
public void SetResult()
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
2020-04-18 21:11:40 +08:00
if (promise != null)
2020-04-18 04:07:59 +08:00
{
2020-04-26 01:38:16 +08:00
promise.TrySetResult();
2020-04-18 04:07:59 +08:00
}
}
// 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 = MoveNextRunner<TStateMachine>.Create(ref stateMachine);
2020-04-18 04:07:59 +08:00
}
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 = MoveNextRunner<TStateMachine>.Create(ref stateMachine);
2020-04-18 04:07:59 +08:00
}
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 AsyncUniTaskMethodBuilder<T>
2020-04-18 04:07:59 +08:00
{
// cache items.
AutoResetUniTaskCompletionSource<T> promise;
IMoveNextRunner runner;
2020-04-18 21:11:40 +08:00
T result;
2020-04-18 04:07:59 +08:00
// 1. Static Create method.
[DebuggerHidden]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static AsyncUniTaskMethodBuilder<T> Create()
2020-04-18 04:07:59 +08:00
{
return default;
}
// 2. TaskLike Task property.
[DebuggerHidden]
public UniTask<T> Task
2020-04-18 04:07:59 +08:00
{
get
{
2020-04-18 21:11:40 +08:00
if (promise != null)
{
return promise.Task;
}
if (runner == null)
2020-04-18 04:07:59 +08:00
{
return UniTask.FromResult(result);
2020-04-18 04:07:59 +08:00
}
2020-04-18 21:11:40 +08:00
promise = AutoResetUniTaskCompletionSource<T>.Create();
2020-04-18 04:07:59 +08:00
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)
{
2020-04-18 21:11:40 +08:00
promise = AutoResetUniTaskCompletionSource<T>.CreateFromException(exception, out _);
}
else
{
2020-04-26 01:38:16 +08:00
promise.TrySetException(exception);
2020-04-18 04:07:59 +08:00
}
}
// 4. SetResult
[DebuggerHidden]
public void SetResult(T result)
{
// runner is finished, return first.
if (runner != null)
{
runner.Return();
runner = null;
}
if (promise == null)
{
2020-04-18 21:11:40 +08:00
this.result = result;
return;
2020-04-18 04:07:59 +08:00
}
2020-04-18 21:11:40 +08:00
2020-04-26 01:38:16 +08:00
promise.TrySetResult(result);
2020-04-18 04:07:59 +08:00
}
// 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 = MoveNextRunner<TStateMachine>.Create(ref stateMachine);
2020-04-18 04:07:59 +08:00
}
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 = MoveNextRunner<TStateMachine>.Create(ref stateMachine);
2020-04-18 04:07:59 +08:00
}
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.
}
}
2019-05-19 23:14:47 +08:00
}
#endif