UTF encode/native: use IntPtr, not byte*, in the native API (avoid "unsafe" declaration)

pull/19511/head
mgravell 5 years ago
parent b6e104f22f
commit b352873461
  1. 53
      src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
  2. 6
      src/csharp/Grpc.Core/Internal/NativeMethods.Generated.cs
  3. 13
      src/csharp/Grpc.Microbenchmarks/Utf8Encode.cs
  4. 4
      templates/src/csharp/Grpc.Core/Internal/native_methods.include

@ -128,7 +128,7 @@ namespace Grpc.Core.Internal
}
}
public unsafe void StartSendStatusFromServer(ISendStatusFromServerCompletionCallback callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
public void StartSendStatusFromServer(ISendStatusFromServerCompletionCallback callback, Status status, MetadataArraySafeHandle metadataArray, bool sendEmptyInitialMetadata,
byte[] optionalPayload, WriteFlags writeFlags)
{
using (completionQueue.NewScope())
@ -146,32 +146,35 @@ namespace Grpc.Core.Internal
maxBytes = MarshalUtils.GetByteCountUTF8(status.Detail);
}
if (maxBytes <= MaxStackAllocBytes)
{ // for small status, we can encode on the stack without touching arrays
// note: if init-locals is disabled, it would be more efficient
// to just stackalloc[MaxStackAllocBytes]; but by default, since we
// expect this to be small and it needs to wipe, just use maxBytes
byte* ptr = stackalloc byte[maxBytes];
int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, ptr, new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
else
{ // for larger status (rare), rent a buffer from the pool and
// use that for encoding
var statusBuffer = ArrayPool<byte>.Shared.Rent(maxBytes);
try
{
fixed (byte* ptr = statusBuffer)
unsafe
{
if (maxBytes <= MaxStackAllocBytes)
{ // for small status, we can encode on the stack without touching arrays
// note: if init-locals is disabled, it would be more efficient
// to just stackalloc[MaxStackAllocBytes]; but by default, since we
// expect this to be small and it needs to wipe, just use maxBytes
byte* ptr = stackalloc byte[maxBytes];
int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, new IntPtr(ptr), new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
else
{ // for larger status (rare), rent a buffer from the pool and
// use that for encoding
var statusBuffer = ArrayPool<byte>.Shared.Rent(maxBytes);
try
{
int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, ptr, new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
fixed (byte* ptr = statusBuffer)
{
int statusBytes = MarshalUtils.GetBytesUTF8(status.Detail, ptr, maxBytes);
Native.grpcsharp_call_send_status_from_server(this, ctx, status.StatusCode, new IntPtr(ptr), new UIntPtr((ulong)statusBytes), metadataArray, sendEmptyInitialMetadata ? 1 : 0,
optionalPayload, optionalPayloadLength, writeFlags).CheckOk();
}
}
finally
{
ArrayPool<byte>.Shared.Return(statusBuffer);
}
}
finally
{
ArrayPool<byte>.Shared.Return(statusBuffer);
}
}
}

@ -475,7 +475,7 @@ namespace Grpc.Core.Internal
public delegate CallError grpcsharp_call_start_duplex_streaming_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags);
public delegate CallError grpcsharp_call_send_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, int sendEmptyInitialMetadata);
public delegate CallError grpcsharp_call_send_close_from_client_delegate(CallSafeHandle call, BatchContextSafeHandle ctx);
public unsafe delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte* statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public delegate CallError grpcsharp_call_send_status_from_server_delegate(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public delegate CallError grpcsharp_call_recv_message_delegate(CallSafeHandle call, BatchContextSafeHandle ctx);
public delegate CallError grpcsharp_call_recv_initial_metadata_delegate(CallSafeHandle call, BatchContextSafeHandle ctx);
public delegate CallError grpcsharp_call_start_serverside_delegate(CallSafeHandle call, BatchContextSafeHandle ctx);
@ -643,7 +643,7 @@ namespace Grpc.Core.Internal
public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx);
[DllImport(ImportName)]
public static unsafe extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte* statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
[DllImport(ImportName)]
public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx);
@ -939,7 +939,7 @@ namespace Grpc.Core.Internal
public static extern CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx);
[DllImport(ImportName)]
public static unsafe extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte* statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
public static extern CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags);
[DllImport(ImportName)]
public static extern CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx);

@ -61,14 +61,11 @@ namespace Grpc.Microbenchmarks
var native = NativeMethods.Get();
// nop the native-call via reflection
unsafe
{
NativeMethods.Delegates.grpcsharp_call_send_status_from_server_delegate nop = (CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte* statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags) => {
completionRegistry.Extract(ctx.Handle).OnComplete(true); // drain the dictionary as we go
return CallError.OK;
};
native.GetType().GetField(nameof(native.grpcsharp_call_send_status_from_server)).SetValue(native, nop);
}
NativeMethods.Delegates.grpcsharp_call_send_status_from_server_delegate nop = (CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags) => {
completionRegistry.Extract(ctx.Handle).OnComplete(true); // drain the dictionary as we go
return CallError.OK;
};
native.GetType().GetField(nameof(native.grpcsharp_call_send_status_from_server)).SetValue(native, nop);
environment = GrpcEnvironment.AddRef();
metadata = MetadataArraySafeHandle.Create(Metadata.Empty);

@ -31,7 +31,7 @@ native_method_signatures = [
'CallError grpcsharp_call_start_duplex_streaming(CallSafeHandle call, BatchContextSafeHandle ctx, MetadataArraySafeHandle metadataArray, CallFlags metadataFlags)',
'CallError grpcsharp_call_send_message(CallSafeHandle call, BatchContextSafeHandle ctx, byte[] sendBuffer, UIntPtr sendBufferLen, WriteFlags writeFlags, int sendEmptyInitialMetadata)',
'CallError grpcsharp_call_send_close_from_client(CallSafeHandle call, BatchContextSafeHandle ctx)',
'CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, byte[] statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags)',
'CallError grpcsharp_call_send_status_from_server(CallSafeHandle call, BatchContextSafeHandle ctx, StatusCode statusCode, IntPtr statusMessage, UIntPtr statusMessageLen, MetadataArraySafeHandle metadataArray, int sendEmptyInitialMetadata, byte[] optionalSendBuffer, UIntPtr optionalSendBufferLen, WriteFlags writeFlags)',
'CallError grpcsharp_call_recv_message(CallSafeHandle call, BatchContextSafeHandle ctx)',
'CallError grpcsharp_call_recv_initial_metadata(CallSafeHandle call, BatchContextSafeHandle ctx)',
'CallError grpcsharp_call_start_serverside(CallSafeHandle call, BatchContextSafeHandle ctx)',
@ -107,4 +107,4 @@ for signature in native_method_signatures:
native_methods.append({'returntype': match.group(1), 'name': match.group(2), 'params': match.group(3), 'comment': match.group(4)})
return list(native_methods)
%></%def>
%></%def>

Loading…
Cancel
Save