Add CancellationToken.WaitUntilCanceled

pull/61/head
neuecc 2020-05-20 11:04:59 +09:00
parent a52c26102b
commit ea9e61c2e1
4 changed files with 109 additions and 13 deletions

View File

@ -378,15 +378,7 @@ ECS, PlayerLoop
TODO: TODO:
```csharp ```csharp
// Setup Entities Loop. var loop = PlayerLoop.GetCurrentPlayerLoop();
var loop = PlayerLoop.GetDefaultPlayerLoop();
foreach (var world in Unity.Entities.World.All)
{
ScriptBehaviourUpdateOrder.UpdatePlayerLoop(world, loop);
loop = PlayerLoop.GetCurrentPlayerLoop();
}
// UniTask PlayerLoop Initialize.
PlayerLoopHelper.Initialize(ref loop); PlayerLoopHelper.Initialize(ref loop);
``` ```

View File

@ -0,0 +1,51 @@
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 CancellationTokenTest
{
[Fact]
public async Task WaitUntilCanceled()
{
var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(1.5));
var now = DateTime.UtcNow;
await cts.Token.WaitUntilCanceled();
var elapsed = DateTime.UtcNow - now;
elapsed.Should().BeGreaterThan(TimeSpan.FromSeconds(1));
}
[Fact]
public void AlreadyCanceled()
{
var cts = new CancellationTokenSource();
cts.Cancel();
cts.Token.WaitUntilCanceled().GetAwaiter().IsCompleted.Should().BeTrue();
}
[Fact]
public void None()
{
CancellationToken.None.WaitUntilCanceled().GetAwaiter().IsCompleted.Should().BeTrue();
}
}
}

View File

@ -1,6 +1,7 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
using System; using System;
using System.Runtime.CompilerServices;
using System.Threading; using System.Threading;
namespace Cysharp.Threading.Tasks namespace Cysharp.Threading.Tasks
@ -9,15 +10,15 @@ namespace Cysharp.Threading.Tasks
{ {
static readonly Action<object> cancellationTokenCallback = Callback; static readonly Action<object> cancellationTokenCallback = Callback;
public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cts) public static (UniTask, CancellationTokenRegistration) ToUniTask(this CancellationToken cancellationToken)
{ {
if (cts.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
return (UniTask.FromCanceled(cts), default(CancellationTokenRegistration)); return (UniTask.FromCanceled(cancellationToken), default(CancellationTokenRegistration));
} }
var promise = new UniTaskCompletionSource(); var promise = new UniTaskCompletionSource();
return (promise.Task, cts.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise)); return (promise.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
} }
static void Callback(object state) static void Callback(object state)
@ -26,6 +27,11 @@ namespace Cysharp.Threading.Tasks
promise.TrySetResult(); promise.TrySetResult();
} }
public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)
{
return new CancellationTokenAwaitable(cancellationToken);
}
public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback) public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
{ {
var restoreFlow = false; var restoreFlow = false;
@ -70,5 +76,46 @@ namespace Cysharp.Threading.Tasks
} }
} }
} }
public struct CancellationTokenAwaitable
{
CancellationToken cancellationToken;
public CancellationTokenAwaitable(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public Awaiter GetAwaiter()
{
return new Awaiter(cancellationToken);
}
public struct Awaiter : ICriticalNotifyCompletion
{
CancellationToken cancellationToken;
public Awaiter(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public bool IsCompleted => !cancellationToken.CanBeCanceled || cancellationToken.IsCancellationRequested;
public void GetResult()
{
}
public void OnCompleted(Action continuation)
{
UnsafeOnCompleted(continuation);
}
public void UnsafeOnCompleted(Action continuation)
{
cancellationToken.RegisterWithoutCaptureExecutionContext(continuation);
}
}
}
} }

View File

@ -38,6 +38,11 @@ public enum MyEnum
public static partial class UnityUIComponentExtensions public static partial class UnityUIComponentExtensions
{ {
@ -123,6 +128,7 @@ public class SandboxMain : MonoBehaviour
UnityEngine.Debug.Log("OK"); UnityEngine.Debug.Log("OK");
await scheduled; // .ConfigureAwait(PlayerLoopTiming.Update); // .WaitAsync(PlayerLoopTiming.Update); await scheduled; // .ConfigureAwait(PlayerLoopTiming.Update); // .WaitAsync(PlayerLoopTiming.Update);