|
|
@ -19,7 +19,9 @@ |
|
|
|
using System; |
|
|
|
using System; |
|
|
|
using System.Collections.Concurrent; |
|
|
|
using System.Collections.Concurrent; |
|
|
|
using System.Collections.Generic; |
|
|
|
using System.Collections.Generic; |
|
|
|
|
|
|
|
using System.Diagnostics; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
using System.Runtime.InteropServices; |
|
|
|
|
|
|
|
using System.Threading; |
|
|
|
using Grpc.Core.Logging; |
|
|
|
using Grpc.Core.Logging; |
|
|
|
using Grpc.Core.Utils; |
|
|
|
using Grpc.Core.Utils; |
|
|
|
|
|
|
|
|
|
|
@ -35,7 +37,7 @@ namespace Grpc.Core.Internal |
|
|
|
|
|
|
|
|
|
|
|
readonly GrpcEnvironment environment; |
|
|
|
readonly GrpcEnvironment environment; |
|
|
|
readonly Dictionary<IntPtr, IOpCompletionCallback> dict = new Dictionary<IntPtr, IOpCompletionCallback>(new IntPtrComparer()); |
|
|
|
readonly Dictionary<IntPtr, IOpCompletionCallback> dict = new Dictionary<IntPtr, IOpCompletionCallback>(new IntPtrComparer()); |
|
|
|
readonly object myLock = new object(); |
|
|
|
SpinLock spinLock = new SpinLock(Debugger.IsAttached); |
|
|
|
IntPtr lastRegisteredKey; // only for testing |
|
|
|
IntPtr lastRegisteredKey; // only for testing |
|
|
|
|
|
|
|
|
|
|
|
public CompletionRegistry(GrpcEnvironment environment) |
|
|
|
public CompletionRegistry(GrpcEnvironment environment) |
|
|
@ -46,11 +48,19 @@ namespace Grpc.Core.Internal |
|
|
|
public void Register(IntPtr key, IOpCompletionCallback callback) |
|
|
|
public void Register(IntPtr key, IOpCompletionCallback callback) |
|
|
|
{ |
|
|
|
{ |
|
|
|
environment.DebugStats.PendingBatchCompletions.Increment(); |
|
|
|
environment.DebugStats.PendingBatchCompletions.Increment(); |
|
|
|
lock (myLock) |
|
|
|
|
|
|
|
|
|
|
|
bool lockTaken = false; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
spinLock.Enter(ref lockTaken); |
|
|
|
|
|
|
|
|
|
|
|
dict.Add(key, callback); |
|
|
|
dict.Add(key, callback); |
|
|
|
this.lastRegisteredKey = key; |
|
|
|
this.lastRegisteredKey = key; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
finally |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (lockTaken) spinLock.Exit(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback, object state) |
|
|
|
public void RegisterBatchCompletion(BatchContextSafeHandle ctx, BatchCompletionDelegate callback, object state) |
|
|
@ -68,11 +78,18 @@ namespace Grpc.Core.Internal |
|
|
|
public IOpCompletionCallback Extract(IntPtr key) |
|
|
|
public IOpCompletionCallback Extract(IntPtr key) |
|
|
|
{ |
|
|
|
{ |
|
|
|
IOpCompletionCallback value = null; |
|
|
|
IOpCompletionCallback value = null; |
|
|
|
lock (myLock) |
|
|
|
bool lockTaken = false; |
|
|
|
|
|
|
|
try |
|
|
|
{ |
|
|
|
{ |
|
|
|
|
|
|
|
spinLock.Enter(ref lockTaken); |
|
|
|
|
|
|
|
|
|
|
|
value = dict[key]; |
|
|
|
value = dict[key]; |
|
|
|
dict.Remove(key); |
|
|
|
dict.Remove(key); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
finally |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (lockTaken) spinLock.Exit(); |
|
|
|
|
|
|
|
} |
|
|
|
environment.DebugStats.PendingBatchCompletions.Decrement(); |
|
|
|
environment.DebugStats.PendingBatchCompletions.Decrement(); |
|
|
|
return value; |
|
|
|
return value; |
|
|
|
} |
|
|
|
} |
|
|
|