-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
using System; | ||
using System.Buffers; | ||
using System.Collections.Generic; | ||
using System.Net.Sockets; | ||
using System.Runtime.InteropServices; | ||
using System.Threading; | ||
using System.Threading.Tasks.Sources; | ||
using Microsoft.Extensions.ObjectPool; | ||
|
||
namespace SuperSocket.Connection | ||
{ | ||
public class SocketSender : SocketAsyncEventArgs, IValueTaskSource<int>, IResettable | ||
{ | ||
private Action<object> _continuation; | ||
|
||
private static readonly Action<object?> _continuationCompleted = _ => { }; | ||
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / build (macos-latest)
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / build (macos-latest)
Check warning on line 16 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / build (macos-latest)
|
||
|
||
public SocketSender() | ||
{ | ||
} | ||
|
||
internal void SetBuffer(in ReadOnlySequence<byte> buffer) | ||
{ | ||
if (buffer.IsSingleSegment) | ||
{ | ||
var segment = GetArrayByMemory(buffer.First); | ||
SetBuffer(segment.Array, segment.Offset, segment.Count); | ||
} | ||
else | ||
{ | ||
var bufferList = new List<ArraySegment<byte>>(); | ||
|
||
foreach (var piece in buffer) | ||
{ | ||
bufferList.Add(GetArrayByMemory(piece)); | ||
} | ||
|
||
BufferList = bufferList; | ||
} | ||
} | ||
|
||
protected override void OnCompleted(SocketAsyncEventArgs e) | ||
{ | ||
var continuation = _continuation; | ||
|
||
if (continuation != null && Interlocked.CompareExchange(ref _continuation, _continuationCompleted, continuation) != null) | ||
{ | ||
var state = UserToken; | ||
UserToken = null; | ||
|
||
ThreadPool.UnsafeQueueUserWorkItem(continuation, state, preferLocal: true); | ||
Check failure on line 51 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check failure on line 51 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / build (macos-latest)
|
||
} | ||
} | ||
|
||
public int GetResult(short token) | ||
{ | ||
return BytesTransferred; | ||
} | ||
|
||
public ValueTaskSourceStatus GetStatus(short token) | ||
{ | ||
if (!ReferenceEquals(_continuation, _continuationCompleted)) | ||
return ValueTaskSourceStatus.Pending; | ||
|
||
return SocketError == SocketError.Success | ||
? ValueTaskSourceStatus.Succeeded | ||
: ValueTaskSourceStatus.Faulted; | ||
} | ||
|
||
public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) | ||
{ | ||
UserToken = state; | ||
|
||
var prevContinuation = Interlocked.CompareExchange(ref _continuation, continuation, null); | ||
|
||
// The task has already completed, so trigger continuation immediately | ||
if (ReferenceEquals(prevContinuation, _continuationCompleted)) | ||
{ | ||
UserToken = null; | ||
ThreadPool.UnsafeQueueUserWorkItem(continuation, state, preferLocal: true); | ||
Check failure on line 80 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / push
Check failure on line 80 in src/SuperSocket.Connection/Sockets/SocketSender.cs GitHub Actions / build (macos-latest)
|
||
} | ||
} | ||
|
||
public bool TryReset() | ||
{ | ||
if (BufferList.Count > 0) | ||
{ | ||
BufferList.Clear(); | ||
} | ||
else | ||
{ | ||
SetBuffer(null, 0, 0); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
private ArraySegment<byte> GetArrayByMemory(ReadOnlyMemory<byte> memory) | ||
{ | ||
if (!MemoryMarshal.TryGetArray<byte>(memory, out var result)) | ||
{ | ||
throw new InvalidOperationException("Buffer backed by array was expected"); | ||
} | ||
|
||
return result; | ||
} | ||
} | ||
} |