-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
bb80f03
commit d4cab88
Showing
7 changed files
with
174 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Runtime.CompilerServices; | ||
using Draco.Compiler.Internal.Solver; | ||
|
||
namespace Draco.Compiler.Internal.Solver.Tasks; | ||
|
||
internal static class SolverTask | ||
{ | ||
public static SolverTask<T> FromResult<T>(ConstraintSolver solver, T result) | ||
{ | ||
var task = new SolverTask<T>(); | ||
task.Awaiter.Solver = solver; | ||
task.Awaiter.SetResult(result, null); | ||
return task; | ||
} | ||
|
||
public static async SolverTask<ImmutableArray<T>> WhenAll<T>(IEnumerable<SolverTask<T>> tasks) | ||
{ | ||
var result = ImmutableArray.CreateBuilder<T>(); | ||
foreach (var task in tasks) result.Add(await task); | ||
return result.ToImmutable(); | ||
} | ||
} | ||
|
||
[AsyncMethodBuilder(typeof(SolverTaskMethodBuilder<>))] | ||
internal struct SolverTask<T> | ||
{ | ||
internal SolverTaskAwaiter<T> Awaiter; | ||
internal readonly ConstraintSolver Solver => this.Awaiter.Solver; | ||
public readonly bool IsCompleted => this.Awaiter.IsCompleted; | ||
public readonly T Result => this.Awaiter.GetResult(); | ||
public readonly SolverTaskAwaiter<T> GetAwaiter() => this.Awaiter; | ||
} |
48 changes: 48 additions & 0 deletions
48
src/Draco.Compiler/Internal/Solver/Tasks/SolverTaskAwaiter.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Runtime.CompilerServices; | ||
using Draco.Compiler.Internal.Binding.Tasks; | ||
using Draco.Compiler.Internal.Solver; | ||
|
||
namespace Draco.Compiler.Internal.Solver.Tasks; | ||
|
||
internal struct SolverTaskAwaiter<T> : INotifyCompletion, IBindingTaskAwaiter | ||
{ | ||
public bool IsCompleted { get; private set; } | ||
public ConstraintSolver Solver { get; set; } | ||
|
||
private T? result; | ||
private Exception? exception; | ||
private List<Action>? completions; | ||
|
||
internal void SetResult(T? result, Exception? exception) | ||
{ | ||
this.IsCompleted = true; | ||
this.result = result; | ||
this.exception = exception; | ||
foreach (var completion in this.completions ?? Enumerable.Empty<Action>()) | ||
{ | ||
completion(); | ||
} | ||
} | ||
|
||
public readonly T GetResult() | ||
{ | ||
if (this.exception is not null) throw this.exception; | ||
return this.result!; | ||
} | ||
|
||
public void OnCompleted(Action completion) | ||
{ | ||
if (this.IsCompleted) | ||
{ | ||
completion(); | ||
} | ||
else | ||
{ | ||
this.completions ??= new(); | ||
this.completions.Add(completion); | ||
} | ||
} | ||
} |
31 changes: 31 additions & 0 deletions
31
src/Draco.Compiler/Internal/Solver/Tasks/SolverTaskCompletionSource.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using System; | ||
using Draco.Compiler.Internal.Solver; | ||
|
||
namespace Draco.Compiler.Internal.Solver.Tasks; | ||
|
||
internal sealed class SolverTaskCompletionSource<T> | ||
{ | ||
public SolverTask<T> Task | ||
{ | ||
get | ||
{ | ||
var task = new SolverTask<T>(); | ||
task.Awaiter = this.Awaiter; | ||
return task; | ||
} | ||
} | ||
public bool IsCompleted => this.Awaiter.IsCompleted; | ||
public T Result => this.Awaiter.GetResult(); | ||
internal ConstraintSolver Solver => this.Awaiter.Solver; | ||
|
||
internal SolverTaskAwaiter<T> Awaiter; | ||
|
||
internal SolverTaskCompletionSource(ConstraintSolver solver) | ||
{ | ||
this.Awaiter.Solver = solver; | ||
} | ||
|
||
public SolverTaskAwaiter<T> GetAwaiter() => this.Awaiter; | ||
public void SetResult(T result) => this.Awaiter.SetResult(result, null); | ||
public void SetException(Exception exception) => this.Awaiter.SetResult(default, exception); | ||
} |
48 changes: 48 additions & 0 deletions
48
src/Draco.Compiler/Internal/Solver/Tasks/SolverTaskMethodBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
using System; | ||
using System.Diagnostics; | ||
using System.Runtime.CompilerServices; | ||
using Draco.Compiler.Internal.Binding.Tasks; | ||
|
||
namespace Draco.Compiler.Internal.Solver.Tasks; | ||
|
||
internal sealed class SolverTaskMethodBuilder<T> | ||
{ | ||
public SolverTask<T> Task => this.task; | ||
private SolverTask<T> task; | ||
|
||
public static SolverTaskMethodBuilder<T> Create() => new(); | ||
|
||
public void Start<TStateMachine>(ref TStateMachine stateMachine) | ||
where TStateMachine : IAsyncStateMachine => stateMachine.MoveNext(); | ||
|
||
public void SetStateMachine(IAsyncStateMachine _) => Debug.Fail("Unused"); | ||
|
||
public void SetException(Exception exception) => this.Task.Awaiter.SetResult(default, exception); | ||
public void SetResult(T result) => this.Task.Awaiter.SetResult(result, null); | ||
|
||
public void AwaitOnCompleted<TAwaiter, TStateMachine>( | ||
ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : INotifyCompletion | ||
where TStateMachine : IAsyncStateMachine | ||
{ | ||
if (awaiter is not IBindingTaskAwaiter syncAwaiter) | ||
{ | ||
throw new NotSupportedException("Only supporting BindingTask."); | ||
} | ||
this.task.Awaiter.Solver = syncAwaiter.Solver; | ||
awaiter.OnCompleted(stateMachine.MoveNext); | ||
} | ||
|
||
public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( | ||
ref TAwaiter awaiter, ref TStateMachine stateMachine) | ||
where TAwaiter : ICriticalNotifyCompletion | ||
where TStateMachine : IAsyncStateMachine | ||
{ | ||
if (awaiter is not IBindingTaskAwaiter syncAwaiter) | ||
{ | ||
throw new NotSupportedException("Only supporting BindingTask."); | ||
} | ||
this.task.Awaiter.Solver = syncAwaiter.Solver; | ||
awaiter.OnCompleted(stateMachine.MoveNext); | ||
} | ||
} |