remove delegate allocation and boxing from cancellation registrations

pull/19610/head
mgravell 6 years ago
parent 59011087b0
commit 39775cf30f
  1. 11
      src/csharp/Grpc.Core.Tests/CallCancellationTest.cs
  2. 10
      src/csharp/Grpc.Core/Internal/AsyncCall.cs
  3. 8
      src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
  4. 3
      src/csharp/Grpc.Core/Internal/ClientResponseStream.cs
  5. 4
      src/csharp/Grpc.Core/Internal/ServerRequestStream.cs

@ -178,5 +178,16 @@ namespace Grpc.Core.Tests
Assert.AreEqual(StatusCode.Cancelled, ex.Status.StatusCode);
}
}
[Test]
public void CanDisposeDefaultCancellationRegistration()
{
// prove that we're fine to dispose default CancellationTokenRegistration
// values without boxing them to IDisposable for a null-check
var obj = default(CancellationTokenRegistration);
obj.Dispose();
using (obj) {}
}
}
}

@ -38,7 +38,7 @@ namespace Grpc.Core.Internal
bool registeredWithChannel;
// Dispose of to de-register cancellation token registration
IDisposable cancellationTokenRegistration;
CancellationTokenRegistration cancellationTokenRegistration;
// Completion of a pending unary response if not null.
TaskCompletionSource<TResponse> unaryResponseTcs;
@ -409,7 +409,7 @@ namespace Grpc.Core.Internal
// deadlock.
// See https://github.com/grpc/grpc/issues/14777
// See https://github.com/dotnet/corefx/issues/14903
cancellationTokenRegistration?.Dispose();
cancellationTokenRegistration.Dispose();
}
protected override bool IsClient
@ -509,11 +509,7 @@ namespace Grpc.Core.Internal
// Make sure that once cancellationToken for this call is cancelled, Cancel() will be called.
private void RegisterCancellationCallback()
{
var token = details.Options.CancellationToken;
if (token.CanBeCanceled)
{
cancellationTokenRegistration = token.Register(() => this.Cancel());
}
cancellationTokenRegistration = RegisterCancellationCallbackForToken(details.Options.CancellationToken);
}
/// <summary>

@ -394,5 +394,13 @@ namespace Grpc.Core.Internal
{
HandleReadFinished(success, receivedMessageReader);
}
internal CancellationTokenRegistration RegisterCancellationCallbackForToken(CancellationToken cancellationToken)
{
if (cancellationToken.CanBeCanceled) return cancellationToken.Register(CancelCallFromToken, this);
return default(CancellationTokenRegistration);
}
private static readonly Action<object> CancelCallFromToken = state => ((AsyncCallBase<TWrite, TRead>)state).Cancel();
}
}

@ -49,8 +49,7 @@ namespace Grpc.Core.Internal
public async Task<bool> MoveNext(CancellationToken token)
{
var cancellationTokenRegistration = token.CanBeCanceled ? token.Register(() => call.Cancel()) : (IDisposable) null;
using (cancellationTokenRegistration)
using (call.RegisterCancellationCallbackForToken(token))
{
var result = await call.ReadMessageAsync().ConfigureAwait(false);
this.current = result;

@ -49,9 +49,7 @@ namespace Grpc.Core.Internal
public async Task<bool> MoveNext(CancellationToken token)
{
var cancellationTokenRegistration = token.CanBeCanceled ? token.Register(() => call.Cancel()) : (IDisposable) null;
using (cancellationTokenRegistration)
using (call.RegisterCancellationCallbackForToken(token))
{
var result = await call.ReadMessageAsync().ConfigureAwait(false);
this.current = result;

Loading…
Cancel
Save