-
Notifications
You must be signed in to change notification settings - Fork 604
Added a synchronous write loop for connections. #1392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 6.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -124,3 +124,9 @@ projects/Unit*/TestResult.xml | |
# Vim | ||
.sw? | ||
.*.sw? | ||
|
||
|
||
################# | ||
## JetBrains Rider | ||
################# | ||
.idea/ |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -78,12 +78,14 @@ class SocketFrameHandler : IFrameHandler | |
private readonly byte[] _frameHeaderBuffer; | ||
private bool _closed; | ||
private ArrayPool<byte> _pool = ArrayPool<byte>.Shared; | ||
private readonly bool _enableSynchronousWriteLoop; | ||
|
||
public SocketFrameHandler(AmqpTcpEndpoint endpoint, | ||
Func<AddressFamily, ITcpClient> socketFactory, | ||
TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout) | ||
TimeSpan connectionTimeout, TimeSpan readTimeout, TimeSpan writeTimeout, bool enableSynchronousWriteLoop) | ||
{ | ||
_endpoint = endpoint; | ||
_enableSynchronousWriteLoop = enableSynchronousWriteLoop; | ||
_frameHeaderBuffer = new byte[6]; | ||
var channel = Channel.CreateUnbounded<ReadOnlyMemory<byte>>( | ||
new UnboundedChannelOptions | ||
|
@@ -134,7 +136,15 @@ public SocketFrameHandler(AmqpTcpEndpoint endpoint, | |
_writer = new BufferedStream(netstream, _socket.Client.SendBufferSize); | ||
|
||
WriteTimeout = writeTimeout; | ||
_writerTask = Task.Run(WriteLoop, CancellationToken.None); | ||
if (_enableSynchronousWriteLoop) | ||
{ | ||
TaskCreationOptions tco = TaskCreationOptions.LongRunning | TaskCreationOptions.DenyChildAttach; | ||
_writerTask = Task.Factory.StartNew(SynchronousWriteLoop, CancellationToken.None, tco, TaskScheduler.Default); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When just using the |
||
} | ||
else | ||
{ | ||
_writerTask = Task.Run(WriteLoop, CancellationToken.None); | ||
} | ||
} | ||
|
||
public AmqpTcpEndpoint Endpoint | ||
|
@@ -270,17 +280,41 @@ private async Task WriteLoop() | |
while (await _channelReader.WaitToReadAsync().ConfigureAwait(false)) | ||
{ | ||
_socket.Client.Poll(_writeableStateTimeoutMicroSeconds, SelectMode.SelectWrite); | ||
while (_channelReader.TryRead(out var memory)) | ||
while (_channelReader.TryRead(out ReadOnlyMemory<byte> memory)) | ||
{ | ||
MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment); | ||
await _writer.WriteAsync(segment.Array, segment.Offset, segment.Count).ConfigureAwait(false); | ||
MemoryPool.Return(segment.Array); | ||
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment)) | ||
{ | ||
if (segment.Array != null) | ||
{ | ||
await _writer.WriteAsync(segment.Array, segment.Offset, segment.Count).ConfigureAwait(false); | ||
MemoryPool.Return(segment.Array); | ||
} | ||
} | ||
} | ||
|
||
await _writer.FlushAsync().ConfigureAwait(false); | ||
} | ||
} | ||
|
||
private void SynchronousWriteLoop() | ||
{ | ||
while (_channelReader.WaitToReadAsync().AsTask().Result) | ||
{ | ||
_socket.Client.Poll(_writeableStateTimeoutMicroSeconds, SelectMode.SelectWrite); | ||
while (_channelReader.TryRead(out ReadOnlyMemory<byte> memory)) | ||
{ | ||
if (MemoryMarshal.TryGetArray(memory, out ArraySegment<byte> segment)) | ||
{ | ||
if (segment.Array != null) | ||
{ | ||
_writer.Write(segment.Array, segment.Offset, segment.Count); | ||
MemoryPool.Return(segment.Array); | ||
} | ||
} | ||
} | ||
_writer.Flush(); | ||
} | ||
} | ||
|
||
private static bool ShouldTryIPv6(AmqpTcpEndpoint endpoint) | ||
{ | ||
return Socket.OSSupportsIPv6 && endpoint.AddressFamily != AddressFamily.InterNetwork; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the default value is
false
, maybe we could remove the init valueThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Making the default more visible is a good idea. I'd not remove it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, I think it's a kind of code style. I prefer to remove it while I would not argue for this.
Have a test on this, the default value would be removed when built in release mode, but would not when in debug mode