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 object staticLock = new object();
static readonly AtomicCounter atomicCounter = new AtomicCounter();
static readonly ConcurrentDictionary<IntPtr, UniversalNativeCallback> registry = new ConcurrentDictionary<IntPtr, UniversalNativeCallback>();
static NativeCallbackDispatcherCallback dispatcherCallback;
@ -54,30 +52,14 @@ namespace Grpc.Core.Internal
public static NativeCallbackRegistration RegisterCallback(UniversalNativeCallback callback)
{
while (true)
{
// 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);
var gcHandle = GCHandle.Alloc(callback);
return new NativeCallbackRegistration(gcHandle);
}
private static bool TryGetCallback(IntPtr tag, out UniversalNativeCallback callback)
private static UniversalNativeCallback GetCallback(IntPtr tag)
{
return registry.TryGetValue(tag, out callback);
}
private static IntPtr NextTag()
{
return (IntPtr) atomicCounter.Increment();
var gcHandle = GCHandle.FromIntPtr(tag);
return (UniversalNativeCallback) gcHandle.Target;
}
[MonoPInvokeCallback(typeof(NativeCallbackDispatcherCallback))]
@ -85,12 +67,7 @@ namespace Grpc.Core.Internal
{
try
{
UniversalNativeCallback callback;
if (!TryGetCallback(tag, out callback))
{
Logger.Error("No native callback handler registered for tag {0}.", tag);
return 0;
}
var callback = GetCallback(tag);
return callback(arg0, arg1, arg2, arg3, arg4, arg5);
}
catch (Exception e)
@ -104,18 +81,21 @@ namespace Grpc.Core.Internal
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()
{
NativeCallbackDispatcher.UnregisterCallback(tag);
if (handle.IsAllocated)
{
handle.Free();
}
}
}
}

Loading…
Cancel
Save