Skip to content

Commit

Permalink
Improve AsyncAutoResetEvent behavior.
Browse files Browse the repository at this point in the history
  • Loading branch information
rubenwe committed Oct 18, 2018
1 parent 3dbffb1 commit d7974fc
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 10 deletions.
53 changes: 53 additions & 0 deletions source/PlanningAI.Tests/AsyncAutoResetEventTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.Threading;
using System.Threading.Tasks;
using PlanningAi.Utils;
using Xunit;

namespace PlanningAI.Tests
{
public class AsyncAutoResetEventTests
{
[Fact]
public void ShouldReleaseOneWaitingTask()
{
var evt = new AsyncAutoResetEvent();

var task1 = evt.WaitAsync();
var task2 = evt.WaitAsync();

evt.Set();

Assert.True(task1.IsCompletedSuccessfully);
Assert.False(task2.IsCompleted);
}

[Fact]
public void ShouldReleaseFirstNonCanceledTask()
{
var source = new CancellationTokenSource();
var evt = new AsyncAutoResetEvent();

var task1 = evt.WaitAsync(source.Token);
var task2 = evt.WaitAsync(default);

source.Cancel();
evt.Set();

Assert.True(task1.IsCanceled);
Assert.True(task2.IsCompletedSuccessfully);
}

[Fact]
public async Task AwaitingCanceledTaskShouldThrow()
{
var evt = new AsyncAutoResetEvent();

var source = new CancellationTokenSource();
var exTask = Assert.ThrowsAsync<TaskCanceledException>(async () => await evt.WaitAsync(source.Token));

source.Cancel();

await exTask;
}
}
}
10 changes: 5 additions & 5 deletions source/PlanningAI.Tests/PlannerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace PlanningAI.Tests
{
public class PlannerTests
{
private const int BenchmarkIterations = 1000;
private const int BenchmarkIterations = 1;

[Fact]
public void FailedPlanningShouldReturnNullPlan()
Expand Down Expand Up @@ -58,10 +58,10 @@ public void PlanningShouldFindWayToReachTargetValue()
var planner = PlannerFactory.CreatePlanner(new PlannerSettings {PlannerType = PlannerType.Regressive});

// WarmUp
for (var i = 0; i < 10; i++)
{
var _ = planner.GetPlan(start, goal, actions);
}
// for (var i = 0; i < 10; i++)
// {
// var _ = planner.GetPlan(start, goal, actions);
// }

PlanningResult result = null;
var sw = Stopwatch.StartNew();
Expand Down
2 changes: 1 addition & 1 deletion source/PlanningAi/PlanningAi.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</PropertyGroup>

<PropertyGroup Condition="$(Configuration) == 'Release'">
<Version>0.10.0</Version>
<Version>0.10.1</Version>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
<Configuration>Release</Configuration>
</PropertyGroup>
Expand Down
15 changes: 11 additions & 4 deletions source/PlanningAi/Utils/AsyncAutoResetEvent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ public sealed class AsyncAutoResetEvent
private readonly object _syncRoot = new object();
private readonly Queue<TaskCompletionSource<bool>> _taskQueue = new Queue<TaskCompletionSource<bool>>();

public async Task WaitAsync(CancellationToken token)
public async Task WaitAsync(CancellationToken token = default)
{
if (token.IsCancellationRequested) return;

var source = new TaskCompletionSource<bool>();
token.Register(() => source.SetCanceled());
if (token.CanBeCanceled)
{
token.Register(() =>
{
if (source.Task.IsCompleted) return;
source.SetCanceled();
});
}

lock (_syncRoot)
{
_taskQueue.Enqueue(source);
Expand All @@ -28,8 +36,7 @@ public void Set()
TaskCompletionSource<bool> source;
while ((source = GetNextQueueEntry()) != null)
{
var task = source.Task;
if (task.IsCanceled || task.IsCompleted) continue;
if (source.Task.IsCompleted) continue;

source.SetResult(true);
return;
Expand Down

0 comments on commit d7974fc

Please sign in to comment.