42
42
using RabbitMQ . Client . Events ;
43
43
using RabbitMQ . Client . Exceptions ;
44
44
using RabbitMQ . Client . Framing . Impl ;
45
- using RabbitMQ . Util ;
46
45
47
46
namespace RabbitMQ . Client . Impl
48
47
{
@@ -57,7 +56,6 @@ internal abstract class ChannelBase : IChannel, IRecoverable
57
56
private readonly RpcContinuationQueue _continuationQueue = new RpcContinuationQueue ( ) ;
58
57
private readonly ManualResetEventSlim _flowControlBlock = new ManualResetEventSlim ( true ) ;
59
58
60
- private readonly object _rpcLock = new object ( ) ;
61
59
private readonly object _confirmLock = new object ( ) ;
62
60
private readonly LinkedList < ulong > _pendingDeliveryTags = new LinkedList < ulong > ( ) ;
63
61
@@ -328,7 +326,8 @@ private void HandleCommand(in IncomingCommand cmd)
328
326
{
329
327
if ( ! DispatchAsynchronous ( in cmd ) ) // Was asynchronous. Already processed. No need to process further.
330
328
{
331
- _continuationQueue . Next ( ) . HandleCommand ( in cmd ) ;
329
+ IRpcContinuation c = _continuationQueue . Next ( ) ;
330
+ c . HandleCommand ( in cmd ) ;
332
331
}
333
332
}
334
333
@@ -337,12 +336,17 @@ protected void ChannelRpc<TMethod>(in TMethod method, ProtocolCommandId returnCo
337
336
{
338
337
var k = new SimpleBlockingRpcContinuation ( ) ;
339
338
IncomingCommand reply ;
340
- lock ( _rpcLock )
339
+ _rpcSemaphore . Wait ( ) ;
340
+ try
341
341
{
342
342
Enqueue ( k ) ;
343
343
Session . Transmit ( in method ) ;
344
344
k . GetReply ( ContinuationTimeout , out reply ) ;
345
345
}
346
+ finally
347
+ {
348
+ _rpcSemaphore . Release ( ) ;
349
+ }
346
350
347
351
reply . ReturnMethodBuffer ( ) ;
348
352
@@ -358,12 +362,17 @@ protected TReturn ChannelRpc<TMethod, TReturn>(in TMethod method, ProtocolComman
358
362
var k = new SimpleBlockingRpcContinuation ( ) ;
359
363
IncomingCommand reply ;
360
364
361
- lock ( _rpcLock )
365
+ _rpcSemaphore . Wait ( ) ;
366
+ try
362
367
{
363
368
Enqueue ( k ) ;
364
369
Session . Transmit ( in method ) ;
365
370
k . GetReply ( ContinuationTimeout , out reply ) ;
366
371
}
372
+ finally
373
+ {
374
+ _rpcSemaphore . Release ( ) ;
375
+ }
367
376
368
377
if ( reply . CommandId != returnCommandId )
369
378
{
@@ -783,13 +792,21 @@ protected void HandleConnectionUnblocked()
783
792
Session . Connection . HandleConnectionUnblocked ( ) ;
784
793
}
785
794
786
- protected void HandleQueueDeclareOk ( in IncomingCommand cmd )
795
+ protected bool HandleQueueDeclareOk ( in IncomingCommand cmd )
787
796
{
788
- var method = new Client . Framing . Impl . QueueDeclareOk ( cmd . MethodBytes . Span ) ;
789
- cmd . ReturnMethodBuffer ( ) ;
790
- var k = ( QueueDeclareRpcContinuation ) _continuationQueue . Next ( ) ;
791
- k . m_result = new QueueDeclareOk ( method . _queue , method . _messageCount , method . _consumerCount ) ;
792
- k . HandleCommand ( IncomingCommand . Empty ) ; // release the continuation.
797
+ if ( _continuationQueue . TryPeek < QueueDeclareRpcContinuation > ( out var k ) )
798
+ {
799
+ _continuationQueue . Next ( ) ;
800
+ var method = new Client . Framing . Impl . QueueDeclareOk ( cmd . MethodBytes . Span ) ;
801
+ cmd . ReturnMethodBuffer ( ) ;
802
+ k . m_result = new QueueDeclareOk ( method . _queue , method . _messageCount , method . _consumerCount ) ;
803
+ k . HandleCommand ( IncomingCommand . Empty ) ; // release the continuation.
804
+ return true ;
805
+ }
806
+ else
807
+ {
808
+ return false ;
809
+ }
793
810
}
794
811
795
812
public abstract void _Private_BasicCancel ( string consumerTag , bool nowait ) ;
@@ -844,12 +861,17 @@ public void BasicCancel(string consumerTag)
844
861
{
845
862
var k = new BasicConsumerRpcContinuation { m_consumerTag = consumerTag } ;
846
863
847
- lock ( _rpcLock )
864
+ _rpcSemaphore . Wait ( ) ;
865
+ try
848
866
{
849
867
Enqueue ( k ) ;
850
868
_Private_BasicCancel ( consumerTag , false ) ;
851
869
k . GetReply ( ContinuationTimeout ) ;
852
870
}
871
+ finally
872
+ {
873
+ _rpcSemaphore . Release ( ) ;
874
+ }
853
875
}
854
876
855
877
public void BasicCancelNoWait ( string consumerTag )
@@ -872,7 +894,8 @@ public string BasicConsume(string queue, bool autoAck, string consumerTag, bool
872
894
873
895
var k = new BasicConsumerRpcContinuation { m_consumer = consumer } ;
874
896
875
- lock ( _rpcLock )
897
+ _rpcSemaphore . Wait ( ) ;
898
+ try
876
899
{
877
900
Enqueue ( k ) ;
878
901
// Non-nowait. We have an unconventional means of getting
@@ -881,6 +904,11 @@ public string BasicConsume(string queue, bool autoAck, string consumerTag, bool
881
904
/*nowait:*/ false , arguments ) ;
882
905
k . GetReply ( ContinuationTimeout ) ;
883
906
}
907
+ finally
908
+ {
909
+ _rpcSemaphore . Release ( ) ;
910
+ }
911
+
884
912
string actualConsumerTag = k . m_consumerTag ;
885
913
886
914
return actualConsumerTag ;
@@ -889,12 +917,18 @@ public string BasicConsume(string queue, bool autoAck, string consumerTag, bool
889
917
public BasicGetResult BasicGet ( string queue , bool autoAck )
890
918
{
891
919
var k = new BasicGetRpcContinuation ( ) ;
892
- lock ( _rpcLock )
920
+
921
+ _rpcSemaphore . Wait ( ) ;
922
+ try
893
923
{
894
924
Enqueue ( k ) ;
895
925
_Private_BasicGet ( queue , autoAck ) ;
896
926
k . GetReply ( ContinuationTimeout ) ;
897
927
}
928
+ finally
929
+ {
930
+ _rpcSemaphore . Release ( ) ;
931
+ }
898
932
899
933
return k . m_result ;
900
934
}
@@ -982,12 +1016,17 @@ public void BasicRecover(bool requeue)
982
1016
{
983
1017
var k = new SimpleBlockingRpcContinuation ( ) ;
984
1018
985
- lock ( _rpcLock )
1019
+ _rpcSemaphore . Wait ( ) ;
1020
+ try
986
1021
{
987
1022
Enqueue ( k ) ;
988
1023
_Private_BasicRecover ( requeue ) ;
989
1024
k . GetReply ( ContinuationTimeout ) ;
990
1025
}
1026
+ finally
1027
+ {
1028
+ _rpcSemaphore . Release ( ) ;
1029
+ }
991
1030
}
992
1031
993
1032
public abstract void BasicRecoverAsync ( bool requeue ) ;
@@ -1065,6 +1104,11 @@ public QueueDeclareOk QueueDeclare(string queue, bool durable, bool exclusive, b
1065
1104
return QueueDeclare ( queue , false , durable , exclusive , autoDelete , arguments ) ;
1066
1105
}
1067
1106
1107
+ public ValueTask < QueueDeclareOk > QueueDeclareAsync ( string queue , bool durable , bool exclusive , bool autoDelete , IDictionary < string , object > arguments )
1108
+ {
1109
+ return QueueDeclareAsync ( queue , false , durable , exclusive , autoDelete , arguments ) ;
1110
+ }
1111
+
1068
1112
public void QueueDeclareNoWait ( string queue , bool durable , bool exclusive , bool autoDelete , IDictionary < string , object > arguments )
1069
1113
{
1070
1114
_Private_QueueDeclare ( queue , false , durable , exclusive , autoDelete , true , arguments ) ;
@@ -1196,17 +1240,44 @@ await CloseAsync(new ShutdownEventArgs(ShutdownInitiator.Library,
1196
1240
private QueueDeclareOk QueueDeclare ( string queue , bool passive , bool durable , bool exclusive , bool autoDelete , IDictionary < string , object > arguments )
1197
1241
{
1198
1242
var k = new QueueDeclareRpcContinuation ( ) ;
1199
- lock ( _rpcLock )
1243
+
1244
+ _rpcSemaphore . Wait ( ) ;
1245
+ try
1200
1246
{
1201
1247
Enqueue ( k ) ;
1202
1248
_Private_QueueDeclare ( queue , passive , durable , exclusive , autoDelete , false , arguments ) ;
1203
1249
k . GetReply ( ContinuationTimeout ) ;
1204
1250
}
1251
+ finally
1252
+ {
1253
+ _rpcSemaphore . Release ( ) ;
1254
+ }
1255
+
1205
1256
QueueDeclareOk result = k . m_result ;
1206
1257
CurrentQueue = result . QueueName ;
1207
1258
return result ;
1208
1259
}
1209
1260
1261
+ private async ValueTask < QueueDeclareOk > QueueDeclareAsync ( string queue , bool passive , bool durable , bool exclusive , bool autoDelete , IDictionary < string , object > arguments )
1262
+ {
1263
+ var k = new QueueDeclareAsyncRpcContinuation ( ) ;
1264
+ await _rpcSemaphore . WaitAsync ( ) . ConfigureAwait ( false ) ;
1265
+ try
1266
+ {
1267
+ Enqueue ( k ) ;
1268
+
1269
+ var method = new QueueDeclare ( queue , passive , durable , exclusive , autoDelete , false , arguments ) ;
1270
+ await ModelSendAsync ( method ) . ConfigureAwait ( false ) ;
1271
+
1272
+ QueueDeclareOk result = await k ;
1273
+ CurrentQueue = result . QueueName ;
1274
+ return result ;
1275
+ }
1276
+ finally
1277
+ {
1278
+ _rpcSemaphore . Release ( ) ;
1279
+ }
1280
+ }
1210
1281
1211
1282
public class BasicConsumerRpcContinuation : SimpleBlockingRpcContinuation
1212
1283
{
@@ -1228,5 +1299,29 @@ public class QueueDeclareRpcContinuation : SimpleBlockingRpcContinuation
1228
1299
{
1229
1300
public QueueDeclareOk m_result ;
1230
1301
}
1302
+
1303
+ public class QueueDeclareAsyncRpcContinuation : AsyncRpcContinuation < QueueDeclareOk >
1304
+ {
1305
+ public override void HandleCommand ( in IncomingCommand cmd )
1306
+ {
1307
+ try
1308
+ {
1309
+ var method = new Client . Framing . Impl . QueueDeclareOk ( cmd . MethodBytes . Span ) ;
1310
+ var result = new QueueDeclareOk ( method . _queue , method . _messageCount , method . _consumerCount ) ;
1311
+ if ( cmd . CommandId == ProtocolCommandId . QueueDeclareOk )
1312
+ {
1313
+ _tcs . TrySetResult ( result ) ;
1314
+ }
1315
+ else
1316
+ {
1317
+ _tcs . SetException ( new InvalidOperationException ( $ "Received unexpected command of type { cmd . CommandId } !") ) ;
1318
+ }
1319
+ }
1320
+ finally
1321
+ {
1322
+ cmd . ReturnMethodBuffer ( ) ;
1323
+ }
1324
+ }
1325
+ }
1231
1326
}
1232
1327
}
0 commit comments