use GCHandle.FromIntPtr

pull/18327/head
Jan Tattermusch 6 years ago
parent 83b6a98872
commit afc2e36803
  1. 48
      src/csharp/Grpc.Core/Internal/NativeCallbackDispatcher.cs

@ -35,8 +35,6 @@ namespace Grpc.Core.Internal
{ {
static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeCallbackDispatcher>(); static readonly ILogger Logger = GrpcEnvironment.Logger.ForType<NativeCallbackDispatcher>();
static readonly object staticLock = new object(); static readonly object staticLock = new object();
static readonly AtomicCounter atomicCounter = new AtomicCounter();
static readonly ConcurrentDictionary<IntPtr, UniversalNativeCallback> registry = new ConcurrentDictionary<IntPtr, UniversalNativeCallback>();
static NativeCallbackDispatcherCallback dispatcherCallback; static NativeCallbackDispatcherCallback dispatcherCallback;
@ -54,30 +52,14 @@ namespace Grpc.Core.Internal
public static NativeCallbackRegistration RegisterCallback(UniversalNativeCallback callback) public static NativeCallbackRegistration RegisterCallback(UniversalNativeCallback callback)
{ {
while (true) var gcHandle = GCHandle.Alloc(callback);
{ return new NativeCallbackRegistration(gcHandle);
// TODO: retries might not work well on 32-bit
var tag = NextTag();
if (registry.TryAdd(tag, callback))
{
return new NativeCallbackRegistration(tag);
}
}
}
public static void UnregisterCallback(IntPtr tag)
{
registry.TryRemove(tag, out UniversalNativeCallback callback);
} }
private static bool TryGetCallback(IntPtr tag, out UniversalNativeCallback callback) private static UniversalNativeCallback GetCallback(IntPtr tag)
{ {
return registry.TryGetValue(tag, out callback); var gcHandle = GCHandle.FromIntPtr(tag);
} return (UniversalNativeCallback) gcHandle.Target;
private static IntPtr NextTag()
{
return (IntPtr) atomicCounter.Increment();
} }
[MonoPInvokeCallback(typeof(NativeCallbackDispatcherCallback))] [MonoPInvokeCallback(typeof(NativeCallbackDispatcherCallback))]
@ -85,12 +67,7 @@ namespace Grpc.Core.Internal
{ {
try try
{ {
UniversalNativeCallback callback; var callback = GetCallback(tag);
if (!TryGetCallback(tag, out callback))
{
Logger.Error("No native callback handler registered for tag {0}.", tag);
return 0;
}
return callback(arg0, arg1, arg2, arg3, arg4, arg5); return callback(arg0, arg1, arg2, arg3, arg4, arg5);
} }
catch (Exception e) catch (Exception e)
@ -104,18 +81,21 @@ namespace Grpc.Core.Internal
internal class NativeCallbackRegistration : IDisposable internal class NativeCallbackRegistration : IDisposable
{ {
readonly IntPtr tag; readonly GCHandle handle;
public NativeCallbackRegistration(IntPtr tag) public NativeCallbackRegistration(GCHandle handle)
{ {
this.tag = tag; this.handle = handle;
} }
public IntPtr Tag => tag; public IntPtr Tag => GCHandle.ToIntPtr(handle);
public void Dispose() public void Dispose()
{ {
NativeCallbackDispatcher.UnregisterCallback(tag); if (handle.IsAllocated)
{
handle.Free();
}
} }
} }
} }

Loading…
Cancel
Save