Skip to content

Commit

Permalink
Add CancellationToken.WaitUntilCanceled
Browse files Browse the repository at this point in the history
  • Loading branch information
neuecc committed May 20, 2020
1 parent a52c261 commit ea9e61c
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 13 deletions.
10 changes: 1 addition & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -378,15 +378,7 @@ ECS, PlayerLoop
TODO:

```csharp
// Setup Entities Loop.
var loop = PlayerLoop.GetDefaultPlayerLoop();
foreach (var world in Unity.Entities.World.All)
{
ScriptBehaviourUpdateOrder.UpdatePlayerLoop(world, loop);
loop = PlayerLoop.GetCurrentPlayerLoop();
}

// UniTask PlayerLoop Initialize.
var loop = PlayerLoop.GetCurrentPlayerLoop();
PlayerLoopHelper.Initialize(ref loop);
```

Expand Down
51 changes: 51 additions & 0 deletions src/UniTask.NetCoreTests/CancellationTokenTest.cs
Original file line number Diff line number Diff line change
@@ -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();
}
}


}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member

using System;
using System.Runtime.CompilerServices;
using System.Threading;

namespace Cysharp.Threading.Tasks
Expand All @@ -9,15 +10,15 @@ public static class CancellationTokenExtensions
{
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();
return (promise.Task, cts.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
return (promise.Task, cancellationToken.RegisterWithoutCaptureExecutionContext(cancellationTokenCallback, promise));
}

static void Callback(object state)
Expand All @@ -26,6 +27,11 @@ static void Callback(object state)
promise.TrySetResult();
}

public static CancellationTokenAwaitable WaitUntilCanceled(this CancellationToken cancellationToken)
{
return new CancellationTokenAwaitable(cancellationToken);
}

public static CancellationTokenRegistration RegisterWithoutCaptureExecutionContext(this CancellationToken cancellationToken, Action callback)
{
var restoreFlow = false;
Expand Down Expand Up @@ -70,5 +76,46 @@ public static CancellationTokenRegistration RegisterWithoutCaptureExecutionConte
}
}
}

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);
}
}
}
}

6 changes: 6 additions & 0 deletions src/UniTask/Assets/Scenes/SandboxMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public enum MyEnum








public static partial class UnityUIComponentExtensions
{

Expand Down Expand Up @@ -123,6 +128,7 @@ async UniTask RunJobAsync()





UnityEngine.Debug.Log("OK");
await scheduled; // .ConfigureAwait(PlayerLoopTiming.Update); // .WaitAsync(PlayerLoopTiming.Update);
Expand Down

0 comments on commit ea9e61c

Please sign in to comment.