Browse Source

Elide repeated Action-delegate allocation by caching it (#1324)

* Elide repeated Action-delegate allocation by caching it

Here C# compiler has too little knowledge about the usage of the delegate, we know better so cache it on our own to avoid the repeated allocation.

* Use conditional compilation
release/3.x.x
Günther Foidl 3 years ago
committed by GitHub
parent
commit
bd40e10a66
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 13 deletions
  1. +8
    -2
      Source/MQTTnet/Implementations/CrossPlatformSocket.cs
  2. +25
    -11
      Source/MQTTnet/Implementations/MqttTcpChannel.cs

+ 8
- 2
Source/MQTTnet/Implementations/CrossPlatformSocket.cs View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
@@ -11,12 +11,14 @@ namespace MQTTnet.Implementations
public sealed class CrossPlatformSocket : IDisposable public sealed class CrossPlatformSocket : IDisposable
{ {
readonly Socket _socket; readonly Socket _socket;
readonly Action _socketDisposeAction;


NetworkStream _networkStream; NetworkStream _networkStream;


public CrossPlatformSocket(AddressFamily addressFamily) public CrossPlatformSocket(AddressFamily addressFamily)
{ {
_socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); _socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp);
_socketDisposeAction = _socket.Dispose;
} }


public CrossPlatformSocket() public CrossPlatformSocket()
@@ -24,12 +26,16 @@ namespace MQTTnet.Implementations
// Having this constructor is important because avoiding the address family as parameter // Having this constructor is important because avoiding the address family as parameter
// will make use of dual mode in the .net framework. // will make use of dual mode in the .net framework.
_socket = new Socket(SocketType.Stream, ProtocolType.Tcp); _socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

_socketDisposeAction = _socket.Dispose;
} }


public CrossPlatformSocket(Socket socket) public CrossPlatformSocket(Socket socket)
{ {
_socket = socket ?? throw new ArgumentNullException(nameof(socket)); _socket = socket ?? throw new ArgumentNullException(nameof(socket));
_networkStream = new NetworkStream(socket, true); _networkStream = new NetworkStream(socket, true);

_socketDisposeAction = _socket.Dispose;
} }


public bool NoDelay public bool NoDelay
@@ -112,7 +118,7 @@ namespace MQTTnet.Implementations
_networkStream?.Dispose(); _networkStream?.Dispose();


// Workaround for: https://github.com/dotnet/corefx/issues/24430 // Workaround for: https://github.com/dotnet/corefx/issues/24430
using (cancellationToken.Register(() => _socket.Dispose()))
using (cancellationToken.Register(_socketDisposeAction))
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();




+ 25
- 11
Source/MQTTnet/Implementations/MqttTcpChannel.cs View File

@@ -18,10 +18,16 @@ namespace MQTTnet.Implementations
{ {
readonly IMqttClientOptions _clientOptions; readonly IMqttClientOptions _clientOptions;
readonly MqttClientTcpOptions _tcpOptions; readonly MqttClientTcpOptions _tcpOptions;
readonly Action _disposeAction;


Stream _stream; Stream _stream;


public MqttTcpChannel(IMqttClientOptions clientOptions)
public MqttTcpChannel()
{
_disposeAction = Dispose;
}

public MqttTcpChannel(IMqttClientOptions clientOptions) : this()
{ {
_clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions)); _clientOptions = clientOptions ?? throw new ArgumentNullException(nameof(clientOptions));
_tcpOptions = (MqttClientTcpOptions)clientOptions.ChannelOptions; _tcpOptions = (MqttClientTcpOptions)clientOptions.ChannelOptions;
@@ -29,7 +35,7 @@ namespace MQTTnet.Implementations
IsSecureConnection = clientOptions.ChannelOptions?.TlsOptions?.UseTls == true; IsSecureConnection = clientOptions.ChannelOptions?.TlsOptions?.UseTls == true;
} }


public MqttTcpChannel(Stream stream, string endpoint, X509Certificate2 clientCertificate)
public MqttTcpChannel(Stream stream, string endpoint, X509Certificate2 clientCertificate) : this()
{ {
_stream = stream ?? throw new ArgumentNullException(nameof(stream)); _stream = stream ?? throw new ArgumentNullException(nameof(stream));


@@ -149,11 +155,15 @@ namespace MQTTnet.Implementations
return 0; return 0;
} }


#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
return await stream.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false);
#else
// Workaround for: https://github.com/dotnet/corefx/issues/24430 // Workaround for: https://github.com/dotnet/corefx/issues/24430
using (cancellationToken.Register(Dispose))
using (cancellationToken.Register(_disposeAction))
{ {
return await stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); return await stream.ReadAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
} }
#endif
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {
@@ -177,18 +187,22 @@ namespace MQTTnet.Implementations


try try
{ {
// Workaround for: https://github.com/dotnet/corefx/issues/24430
using (cancellationToken.Register(Dispose))
{
var stream = _stream;
var stream = _stream;


if (stream == null)
{
throw new MqttCommunicationException("The TCP connection is closed.");
}
if (stream == null)
{
throw new MqttCommunicationException("The TCP connection is closed.");
}


#if NETCOREAPP3_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
await stream.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false);
#else
// Workaround for: https://github.com/dotnet/corefx/issues/24430
using (cancellationToken.Register(_disposeAction))
{
await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false); await stream.WriteAsync(buffer, offset, count, cancellationToken).ConfigureAwait(false);
} }
#endif
} }
catch (ObjectDisposedException) catch (ObjectDisposedException)
{ {


Loading…
Cancel
Save