In .NET Core, IUniTaskSource implements IValueTaskSource and implicit, zero overhead conversion
parent
f3e3ba8864
commit
51ba740413
|
@ -1,123 +1,19 @@
|
||||||
#pragma warning disable 0649
|
#pragma warning disable 0649
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Threading.Tasks.Sources;
|
|
||||||
|
|
||||||
namespace Cysharp.Threading.Tasks
|
namespace Cysharp.Threading.Tasks
|
||||||
{
|
{
|
||||||
public static class UniTaskValueTaskExtensions
|
public static class UniTaskValueTaskExtensions
|
||||||
{
|
{
|
||||||
public static ValueTask AsValueTask(this UniTask task)
|
public static ValueTask AsValueTask(this in UniTask task)
|
||||||
{
|
{
|
||||||
ref var core = ref Unsafe.As<UniTask, UniTaskToValueTask>(ref task);
|
return task;
|
||||||
if (core.source == null)
|
|
||||||
{
|
|
||||||
return default;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValueTask(new UniTaskValueTaskSource(core.source), core.token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ValueTask<T> AsValueTask<T>(this UniTask<T> task)
|
public static ValueTask<T> AsValueTask<T>(this in UniTask<T> task)
|
||||||
{
|
{
|
||||||
ref var core = ref Unsafe.As<UniTask<T>, UniTaskToValueTask<T>>(ref task);
|
return task;
|
||||||
if (core.source == null)
|
|
||||||
{
|
|
||||||
return new ValueTask<T>(core.result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new ValueTask<T>(new UniTaskValueTaskSource<T>(core.source), core.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UniTaskToValueTask
|
|
||||||
{
|
|
||||||
public IUniTaskSource source;
|
|
||||||
public short token;
|
|
||||||
}
|
|
||||||
|
|
||||||
class UniTaskValueTaskSource : IValueTaskSource
|
|
||||||
{
|
|
||||||
readonly IUniTaskSource source;
|
|
||||||
|
|
||||||
public UniTaskValueTaskSource(IUniTaskSource source)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetResult(short token)
|
|
||||||
{
|
|
||||||
source.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTaskSourceStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
var status = source.GetStatus(token);
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case UniTaskStatus.Pending:
|
|
||||||
return ValueTaskSourceStatus.Pending;
|
|
||||||
case UniTaskStatus.Succeeded:
|
|
||||||
return ValueTaskSourceStatus.Succeeded;
|
|
||||||
case UniTaskStatus.Faulted:
|
|
||||||
return ValueTaskSourceStatus.Faulted;
|
|
||||||
case UniTaskStatus.Canceled:
|
|
||||||
return ValueTaskSourceStatus.Canceled;
|
|
||||||
default:
|
|
||||||
return (ValueTaskSourceStatus)status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
|
||||||
{
|
|
||||||
source.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct UniTaskToValueTask<T>
|
|
||||||
{
|
|
||||||
public IUniTaskSource<T> source;
|
|
||||||
public T result;
|
|
||||||
public short token;
|
|
||||||
}
|
|
||||||
|
|
||||||
class UniTaskValueTaskSource<T> : IValueTaskSource<T>
|
|
||||||
{
|
|
||||||
readonly IUniTaskSource<T> source;
|
|
||||||
|
|
||||||
public UniTaskValueTaskSource(IUniTaskSource<T> source)
|
|
||||||
{
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T GetResult(short token)
|
|
||||||
{
|
|
||||||
return source.GetResult(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ValueTaskSourceStatus GetStatus(short token)
|
|
||||||
{
|
|
||||||
var status = source.GetStatus(token);
|
|
||||||
switch (status)
|
|
||||||
{
|
|
||||||
case UniTaskStatus.Pending:
|
|
||||||
return ValueTaskSourceStatus.Pending;
|
|
||||||
case UniTaskStatus.Succeeded:
|
|
||||||
return ValueTaskSourceStatus.Succeeded;
|
|
||||||
case UniTaskStatus.Faulted:
|
|
||||||
return ValueTaskSourceStatus.Faulted;
|
|
||||||
case UniTaskStatus.Canceled:
|
|
||||||
return ValueTaskSourceStatus.Canceled;
|
|
||||||
default:
|
|
||||||
return (ValueTaskSourceStatus)status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags)
|
|
||||||
{
|
|
||||||
source.OnCompleted(continuation, state, token);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.1</TargetFramework>
|
||||||
<AssemblyName>UniTask</AssemblyName>
|
<AssemblyName>UniTask</AssemblyName>
|
||||||
|
<LangVersion>8.0</LangVersion>
|
||||||
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
<RootNamespace>Cysharp.Threading.Tasks</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,25 @@ namespace NetCoreSandbox
|
||||||
public string text { get; set; }
|
public string text { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ZeroAllocAsyncAwaitInDotNetCore
|
||||||
|
{
|
||||||
|
public ValueTask<int> NanikaAsync(int x, int y)
|
||||||
|
{
|
||||||
|
return Core(this, x, y);
|
||||||
|
|
||||||
|
static async UniTask<int> Core(ZeroAllocAsyncAwaitInDotNetCore self, int x, int y)
|
||||||
|
{
|
||||||
|
// nanika suru...
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(x + y));
|
||||||
|
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static partial class UnityUIComponentExtensions
|
public static partial class UnityUIComponentExtensions
|
||||||
{
|
{
|
||||||
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text)
|
public static void BindTo(this IUniTaskAsyncEnumerable<string> source, Text text)
|
||||||
|
@ -88,8 +107,10 @@ namespace NetCoreSandbox
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void Main(string[] args)
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
|
var foo = await new ZeroAllocAsyncAwaitInDotNetCore().NanikaAsync(1, 2);
|
||||||
|
Console.WriteLine(foo);
|
||||||
|
|
||||||
var channel = Channel.CreateSingleConsumerUnbounded<int>();
|
var channel = Channel.CreateSingleConsumerUnbounded<int>();
|
||||||
|
|
||||||
|
@ -99,7 +120,7 @@ namespace NetCoreSandbox
|
||||||
|
|
||||||
var token = cts.Token;
|
var token = cts.Token;
|
||||||
|
|
||||||
FooAsync(token).ForEachAsync(x => { }, token);
|
await FooAsync(token).ForEachAsync(x => { }, token);
|
||||||
|
|
||||||
|
|
||||||
// Observable.Range(1,10).CombineLatest(
|
// Observable.Range(1,10).CombineLatest(
|
||||||
|
|
|
@ -19,17 +19,75 @@ namespace Cysharp.Threading.Tasks
|
||||||
|
|
||||||
// similar as IValueTaskSource
|
// similar as IValueTaskSource
|
||||||
public interface IUniTaskSource
|
public interface IUniTaskSource
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
: System.Threading.Tasks.Sources.IValueTaskSource
|
||||||
|
#pragma warning disable CS0108
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
UniTaskStatus GetStatus(short token);
|
UniTaskStatus GetStatus(short token);
|
||||||
void OnCompleted(Action<object> continuation, object state, short token);
|
void OnCompleted(Action<object> continuation, object state, short token);
|
||||||
void GetResult(short token);
|
void GetResult(short token);
|
||||||
|
|
||||||
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
UniTaskStatus UnsafeGetStatus(); // only for debug use.
|
||||||
|
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
#pragma warning restore CS0108
|
||||||
|
|
||||||
|
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource.GetStatus(short token)
|
||||||
|
{
|
||||||
|
return (System.Threading.Tasks.Sources.ValueTaskSourceStatus)(int)((IUniTaskSource)this).GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System.Threading.Tasks.Sources.IValueTaskSource.GetResult(short token)
|
||||||
|
{
|
||||||
|
((IUniTaskSource)this).GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System.Threading.Tasks.Sources.IValueTaskSource.OnCompleted(Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags)
|
||||||
|
{
|
||||||
|
// ignore flags, always none.
|
||||||
|
((IUniTaskSource)this).OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IUniTaskSource<out T> : IUniTaskSource
|
public interface IUniTaskSource<out T> : IUniTaskSource
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
, System.Threading.Tasks.Sources.IValueTaskSource<T>
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
new T GetResult(short token);
|
new T GetResult(short token);
|
||||||
|
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
|
new public UniTaskStatus GetStatus(short token)
|
||||||
|
{
|
||||||
|
return ((IUniTaskSource)this).GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
new public void OnCompleted(Action<object> continuation, object state, short token)
|
||||||
|
{
|
||||||
|
((IUniTaskSource)this).OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.Threading.Tasks.Sources.ValueTaskSourceStatus System.Threading.Tasks.Sources.IValueTaskSource<T>.GetStatus(short token)
|
||||||
|
{
|
||||||
|
return (System.Threading.Tasks.Sources.ValueTaskSourceStatus)(int)((IUniTaskSource)this).GetStatus(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
T System.Threading.Tasks.Sources.IValueTaskSource<T>.GetResult(short token)
|
||||||
|
{
|
||||||
|
return ((IUniTaskSource<T>)this).GetResult(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
void System.Threading.Tasks.Sources.IValueTaskSource<T>.OnCompleted(Action<object> continuation, object state, short token, System.Threading.Tasks.Sources.ValueTaskSourceOnCompletedFlags flags)
|
||||||
|
{
|
||||||
|
// ignore flags, always none.
|
||||||
|
((IUniTaskSource)this).OnCompleted(continuation, state, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UniTaskStatusExtensions
|
public static class UniTaskStatusExtensions
|
||||||
|
|
|
@ -68,6 +68,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
return new UniTask<bool>(new IsCanceledSource(source), token);
|
return new UniTask<bool>(new IsCanceledSource(source), token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
|
public static implicit operator System.Threading.Tasks.ValueTask(in UniTask self)
|
||||||
|
{
|
||||||
|
if (self.source == null)
|
||||||
|
{
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new System.Threading.Tasks.ValueTask(self.source, self.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
if (source == null) return "()";
|
if (source == null) return "()";
|
||||||
|
@ -414,6 +428,20 @@ namespace Cysharp.Threading.Tasks
|
||||||
return self.AsUniTask();
|
return self.AsUniTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !UNITY_2018_3_OR_NEWER
|
||||||
|
|
||||||
|
public static implicit operator System.Threading.Tasks.ValueTask<T>(in UniTask<T> self)
|
||||||
|
{
|
||||||
|
if (self.source == null)
|
||||||
|
{
|
||||||
|
return new System.Threading.Tasks.ValueTask<T>(self.result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new System.Threading.Tasks.ValueTask<T>(self.source, self.token);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// returns (bool IsCanceled, T Result) instead of throws OperationCanceledException.
|
/// returns (bool IsCanceled, T Result) instead of throws OperationCanceledException.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in New Issue