Skip to content

Commit 4b51520

Browse files
hadashiAclaude
andcommitted
Fix netstandard2.1 build: avoid Task.WaitAsync
Task.WaitAsync(CancellationToken) is .NET 6+, but ChibiRuby also targets netstandard2.1. Replace it with a hand-rolled WhenAny-based wait inside WaitForTerminateAsync so all four TFMs compile. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ace1b64 commit 4b51520

1 file changed

Lines changed: 23 additions & 3 deletions

File tree

src/ChibiRuby/RFiber.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,31 @@ public ValueTask<MRubyValue> WaitForResumeAsync(CancellationToken cancellation =
5353
public ValueTask<MRubyValue> WaitForTerminateAsync(CancellationToken cancellation = default)
5454
{
5555
var task = terminationSource.Task;
56-
if (cancellation.CanBeCanceled)
56+
if (!cancellation.CanBeCanceled)
5757
{
58-
task = task.WaitAsync(cancellation);
58+
return new ValueTask<MRubyValue>(task);
59+
}
60+
return AwaitWithCancellationAsync(task, cancellation);
61+
62+
// Hand-rolled equivalent of Task.WaitAsync(cancellation): the latter
63+
// only exists on .NET 6+, but this assembly also targets
64+
// netstandard2.1.
65+
static async ValueTask<MRubyValue> AwaitWithCancellationAsync(
66+
Task<MRubyValue> task, CancellationToken cancellation)
67+
{
68+
var cancelTcs = new TaskCompletionSource<bool>(
69+
TaskCreationOptions.RunContinuationsAsynchronously);
70+
using (cancellation.Register(
71+
static state => ((TaskCompletionSource<bool>)state!).TrySetResult(true),
72+
cancelTcs))
73+
{
74+
if (await Task.WhenAny(task, cancelTcs.Task).ConfigureAwait(false) != task)
75+
{
76+
cancellation.ThrowIfCancellationRequested();
77+
}
78+
}
79+
return await task.ConfigureAwait(false);
5980
}
60-
return new ValueTask<MRubyValue>(task);
6181
}
6282

6383
public async IAsyncEnumerable<MRubyValue> AsAsyncEnumerable([EnumeratorCancellation] CancellationToken cancellation = default)

0 commit comments

Comments
 (0)