Add UniTask.Defer
parent
d36e7987b3
commit
7b273c4bd1
|
@ -0,0 +1,47 @@
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Channels;
|
||||||
|
using Cysharp.Threading.Tasks.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace NetCoreTests
|
||||||
|
{
|
||||||
|
public class DeferTest
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task D()
|
||||||
|
{
|
||||||
|
var created = false;
|
||||||
|
var v = UniTask.Defer(() => { created = true; return UniTask.Run(() => 10); });
|
||||||
|
|
||||||
|
created.Should().BeFalse();
|
||||||
|
|
||||||
|
var t = await v;
|
||||||
|
|
||||||
|
created.Should().BeTrue();
|
||||||
|
|
||||||
|
t.Should().Be(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task D2()
|
||||||
|
{
|
||||||
|
var created = false;
|
||||||
|
var v = UniTask.Defer(() => { created = true; return UniTask.Run(() => 10).AsUniTask(); });
|
||||||
|
|
||||||
|
created.Should().BeFalse();
|
||||||
|
|
||||||
|
await v;
|
||||||
|
|
||||||
|
created.Should().BeTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -132,6 +132,101 @@ namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
asyncAction(state).Forget();
|
asyncAction(state).Forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defer the task creation just before call await.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask Defer(Func<UniTask> factory)
|
||||||
|
{
|
||||||
|
return new UniTask(new DeferPromise(factory), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defer the task creation just before call await.
|
||||||
|
/// </summary>
|
||||||
|
public static UniTask<T> Defer<T>(Func<UniTask<T>> factory)
|
||||||
|
{
|
||||||
|
return new UniTask<T>(new DeferPromise<T>(factory), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DeferPromise : IUniTaskSource
|
||||||
|
{
|
||||||
|
Func<UniTask> factory;
|
||||||
|
UniTask task;
|
||||||
|
UniTask.Awaiter awaiter;
|
||||||
|
|
||||||
|
public DeferPromise(Func<UniTask> factory)
|
||||||
|
{
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetResult(short token)
|
||||||
|
{
|
||||||
|
awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
|
|
||||||
|
task = f();
|
||||||
|
awaiter = f().GetAwaiter();
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sealed class DeferPromise<T> : IUniTaskSource<T>
|
||||||
|
{
|
||||||
|
Func<UniTask<T>> factory;
|
||||||
|
UniTask<T> task;
|
||||||
|
UniTask<T>.Awaiter awaiter;
|
||||||
|
|
||||||
|
public DeferPromise(Func<UniTask<T>> factory)
|
||||||
|
{
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetResult(short token)
|
||||||
|
{
|
||||||
|
return awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IUniTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
awaiter.GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
var f = Interlocked.Exchange(ref factory, null);
|
||||||
|
if (f == null) throw new InvalidOperationException("Can't call twice.");
|
||||||
|
|
||||||
|
task = f();
|
||||||
|
awaiter = f().GetAwaiter();
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
awaiter.SourceOnCompleted(continuation, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UniTaskStatus UnsafeGetStatus()
|
||||||
|
{
|
||||||
|
return task.Status;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static class CompletedTasks
|
internal static class CompletedTasks
|
||||||
|
|
Loading…
Reference in New Issue