-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
…xists in the dictionary
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,53 +1,88 @@ | ||
using System.Collections.Generic; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Runtime.CompilerServices; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using RabbitMQ.Util; | ||
|
||
namespace RabbitMQ.Client.ConsumerDispatching | ||
{ | ||
#nullable enable | ||
internal abstract class ConsumerDispatcherBase | ||
{ | ||
private static readonly FallbackConsumer fallbackConsumer = new FallbackConsumer(); | ||
private readonly Dictionary<string, IBasicConsumer> _consumers; | ||
private readonly Dictionary<ReadOnlyMemory<byte>, (IBasicConsumer consumer, string consumerTag)> _consumers; | ||
|
||
public IBasicConsumer? DefaultConsumer { get; set; } | ||
|
||
protected ConsumerDispatcherBase() | ||
{ | ||
_consumers = new Dictionary<string, IBasicConsumer>(); | ||
_consumers = new Dictionary<ReadOnlyMemory<byte>, (IBasicConsumer, string)>(MemoryOfByteEqualityComparer.Instance); | ||
} | ||
|
||
protected void AddConsumer(IBasicConsumer consumer, string tag) | ||
{ | ||
lock (_consumers) | ||
{ | ||
_consumers[tag] = consumer; | ||
var tagBytes = Encoding.UTF8.GetBytes(tag); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
_consumers[tagBytes] = (consumer, tag); | ||
} | ||
} | ||
|
||
protected IBasicConsumer GetConsumerOrDefault(string tag) | ||
protected (IBasicConsumer consumer, string consumerTag) GetConsumerOrDefault(ReadOnlyMemory<byte> tag) | ||
{ | ||
lock (_consumers) | ||
{ | ||
return _consumers.TryGetValue(tag, out var consumer) ? consumer : GetDefaultOrFallbackConsumer(); | ||
if (_consumers.TryGetValue(tag, out var consumerPair)) | ||
{ | ||
return consumerPair; | ||
} | ||
|
||
#if NETCOREAPP | ||
This comment has been minimized.
Sorry, something went wrong.
zgabi
Owner
|
||
var consumerTag = Encoding.UTF8.GetString(tag.Span); | ||
#else | ||
string consumerTag; | ||
unsafe | ||
{ | ||
fixed (byte* bytes = tag.Span) | ||
{ | ||
consumerTag = Encoding.UTF8.GetString(bytes, tag.Length); | ||
} | ||
} | ||
#endif | ||
|
||
return (GetDefaultOrFallbackConsumer(), consumerTag); | ||
} | ||
} | ||
|
||
public IBasicConsumer GetAndRemoveConsumer(string tag) | ||
{ | ||
lock (_consumers) | ||
{ | ||
return _consumers.Remove(tag, out var consumer) ? consumer : GetDefaultOrFallbackConsumer(); | ||
var utf8 = Encoding.UTF8; | ||
#if NETCOREAPP | ||
This comment has been minimized.
Sorry, something went wrong.
danielmarbach
|
||
var pool = ArrayPool<byte>.Shared; | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
zgabi
Owner
|
||
var buf = pool.Rent(utf8.GetMaxByteCount(tag.Length)); | ||
int count = utf8.GetBytes(tag, buf); | ||
var memory = buf.AsMemory(0, count); | ||
#else | ||
var memory = utf8.GetBytes(tag).AsMemory(); | ||
This comment has been minimized.
Sorry, something went wrong.
zgabi
Owner
|
||
#endif | ||
var result = _consumers.Remove(memory, out var consumerPair) ? consumerPair.consumer : GetDefaultOrFallbackConsumer(); | ||
#if NETCOREAPP | ||
pool.Return(buf); | ||
#endif | ||
return result; | ||
} | ||
} | ||
|
||
public Task ShutdownAsync(ShutdownEventArgs reason) | ||
{ | ||
lock (_consumers) | ||
{ | ||
foreach (KeyValuePair<string, IBasicConsumer> pair in _consumers) | ||
foreach (KeyValuePair<ReadOnlyMemory<byte>, (IBasicConsumer consumer, string consumerTag)> pair in _consumers) | ||
{ | ||
ShutdownConsumer(pair.Value, reason); | ||
ShutdownConsumer(pair.Value.consumer, reason); | ||
} | ||
_consumers.Clear(); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,6 @@ | |
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Runtime.CompilerServices; | ||
|
||
using RabbitMQ.Client.Exceptions; | ||
This comment has been minimized.
Sorry, something went wrong.
zgabi
Owner
|
||
using RabbitMQ.Util; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace RabbitMQ.Util; | ||
|
||
public sealed class MemoryOfByteEqualityComparer : IEqualityComparer<ReadOnlyMemory<byte>> | ||
{ | ||
public static MemoryOfByteEqualityComparer Instance { get; } = new MemoryOfByteEqualityComparer(); | ||
|
||
public bool Equals(ReadOnlyMemory<byte> left, ReadOnlyMemory<byte> right) | ||
{ | ||
return left.Span.SequenceEqual(right.Span); | ||
} | ||
|
||
public int GetHashCode(ReadOnlyMemory<byte> value) | ||
{ | ||
#if NETSTANDARD | ||
unchecked | ||
{ | ||
int hashCode = 0; | ||
foreach (byte item in value.Span) | ||
This comment has been minimized.
Sorry, something went wrong.
zgabi
Owner
|
||
{ | ||
hashCode = (hashCode * 397) ^ item.GetHashCode(); | ||
} | ||
|
||
return hashCode; | ||
} | ||
#else | ||
HashCode result = default; | ||
result.AddBytes(value.Span); | ||
return result.ToHashCode(); | ||
#endif | ||
} | ||
} |
This is a new byte[] allocation, but hopefully AddConsumer is called more infrequently than the Dispatch method