unsafe void ProcessSendCompletes(object o) { const int maxResults = 1024; RIO_RESULT * results = stackalloc RIO_RESULT[maxResults]; uint count; IntPtr key, bytes; NativeOverlapped *overlapped = stackalloc NativeOverlapped[1]; while (true) { RioStatic.Notify(SendCompletionQueue); if (Kernel32.GetQueuedCompletionStatus(SendCompletionPort, out bytes, out key, out overlapped, -1) != 0) { do { count = RioStatic.DequeueCompletion(SendCompletionQueue, (IntPtr)results, maxResults); WinSock.ThrowLastWSAError(); for (var i = 0; i < count; i++) { var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation]; if (buf.AutoFree) { buf.Dispose(); } } } while (count > 0); } else { Kernel32.ThrowLastError(); } } }
internal int TryGetCompletionResults(CancellationToken cancellationToken, RIO_RESULT *results, int maxCompletionResults) { var completionQueue = QueueHandle; var spinwait = new SpinWait(); while (!cancellationToken.IsCancellationRequested) { var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults); if (resultCount == 0) { spinwait.SpinOnce(); continue; } if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ) { WinSock.ThrowLastWsaError(); break; } return((int)resultCount); } return(0); }
public SendCompletionProcessor(ZerioConfiguration configuration, RioCompletionQueue sendCompletionQueue) { _configuration = configuration; _sendCompletionQueue = sendCompletionQueue; _completionResults = new RIO_RESULT[configuration.MaxSendCompletionResults]; _completionResultsHandle = GCHandle.Alloc(_completionResults, GCHandleType.Pinned); _completionResultsPointer = (RIO_RESULT *)_completionResultsHandle.AddrOfPinnedObject().ToPointer(); }
public SendCompletionProcessor(InternalZerioConfiguration configuration, IRioCompletionQueue sendCompletionQueue) { _sendCompletionQueue = sendCompletionQueue; _completionResults = new RIO_RESULT[configuration.MaxSendCompletionResults]; _completionResultsHandle = GCHandle.Alloc(_completionResults, GCHandleType.Pinned); _completionResultsPointer = (RIO_RESULT *)_completionResultsHandle.AddrOfPinnedObject().ToPointer(); _waitStrategy = CompletionPollingWaitStrategyFactory.Create(configuration.SendCompletionPollingWaitStrategyType); }
internal int TryGetCompletionResults(RIO_RESULT *results, int maxCompletionResults) { var completionQueue = QueueHandle; var resultCount = WinSock.Extensions.DequeueCompletion(completionQueue, results, (uint)maxCompletionResults); if (resultCount == WinSock.Consts.RIO_CORRUPT_CQ) { WinSock.ThrowLastWsaError(); } return((int)resultCount); }
unsafe void ProcessReceiveCompletes(object o) { uint maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue); RIO_RESULT * results = stackalloc RIO_RESULT[(int)maxResults]; uint count; IntPtr key, bytes; NativeOverlapped *overlapped = stackalloc NativeOverlapped[1]; RIO_RESULT result; RioBufferSegment buf; while (true) { RioStatic.Notify(ReceiveCompletionQueue); if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0) { do { count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, results, maxResults); if (count == 0xFFFFFFFF) { WinSock.ThrowLastWSAError(); } for (var i = 0; i < count; i++) { result = results[i]; buf = ReceiveBufferPool.AllSegments[result.RequestCorrelation]; buf.SegmentPointer->Length = (int)result.BytesTransferred; buf.Set(); } } while (count > 0); } else { var error = Marshal.GetLastWin32Error(); if (error == 0 || error == 735) { break; } else if (error == 126) { continue; } else { throw new Win32Exception(error); } } } }
unsafe void ProcessReceiveCompletes(object o) { uint maxResults = Math.Min(MaxOutstandingReceive, int.MaxValue); RIO_RESULT * results = stackalloc RIO_RESULT[(int)maxResults]; RioSocket connection; uint count; IntPtr key, bytes; NativeOverlapped *overlapped = stackalloc NativeOverlapped[1]; RIO_RESULT result; RioBufferSegment buf; while (true) { RioStatic.Notify(ReceiveCompletionQueue); WinSock.ThrowLastWSAError(); if (Kernel32.GetQueuedCompletionStatus(ReceiveCompletionPort, out bytes, out key, out overlapped, -1) != 0) { do { count = RioStatic.DequeueCompletion(ReceiveCompletionQueue, (IntPtr)results, maxResults); if (count == 0xFFFFFFFF) { WinSock.ThrowLastWSAError(); } for (var i = 0; i < count; i++) { result = results[i]; buf = ReceiveBufferPool.AllSegments[result.RequestCorrelation]; if (activeSockets.TryGetValue(result.ConnectionCorrelation, out connection)) { buf.SegmentPointer->Length = (int)result.BytesTransferred; connection.onIncommingSegment(connection, buf); } else { buf.Dispose(); } } } while (count > 0); } else { Kernel32.ThrowLastError(); } } }
public unsafe int TryGetCompletionResults(RIO_RESULT *results, int maxCompletionResults) { if (!AvailableResults.TryDequeue(out var resultArray)) { return(0); } var upperBound = Math.Min(resultArray.Length, maxCompletionResults); for (var i = 0; i < upperBound; i++) { results[i] = resultArray[i]; } return(upperBound); }
unsafe void ProcessSendCompletes(object o) { uint maxResults = Math.Min(MaxOutstandingSend, int.MaxValue); RIO_RESULT * results = stackalloc RIO_RESULT[(int)maxResults]; uint count; IntPtr key, bytes; NativeOverlapped *overlapped = stackalloc NativeOverlapped[1]; while (true) { RioStatic.Notify(SendCompletionQueue); if (Kernel32.GetQueuedCompletionStatus(SendCompletionPort, out bytes, out key, out overlapped, -1) != 0) { do { count = RioStatic.DequeueCompletion(SendCompletionQueue, results, maxResults); if (count == 0xFFFFFFFF) { WinSock.ThrowLastWSAError(); } for (var i = 0; i < count; i++) { var buf = SendBufferPool.AllSegments[results[i].RequestCorrelation]; buf.Set(); } } while (count > 0); } else { var error = Marshal.GetLastWin32Error(); if (error != 0 && error != 735) { throw new Win32Exception(error); } else { break; } } } }
private unsafe void Process(int id) { RIO_RESULT * results = stackalloc RIO_RESULT[maxResults]; uint bytes, key; NativeOverlapped *overlapped; var worker = _workers[id]; var completionPort = worker.completionPort; var cq = worker.completionQueue; PooledSegment cachedOKBuffer = worker.bufferPool.GetBuffer(); Buffer.BlockCopy(_okResponseBytes, 0, cachedOKBuffer.Buffer, cachedOKBuffer.Offset, _okResponseBytes.Length); cachedOKBuffer.RioBuffer.Length = (uint)_okResponseBytes.Length; worker.cachedOK = cachedOKBuffer.RioBuffer; PooledSegment cachedBusyBuffer = worker.bufferPool.GetBuffer(); Buffer.BlockCopy(_busyResponseBytes, 0, cachedBusyBuffer.Buffer, cachedBusyBuffer.Offset, _busyResponseBytes.Length); cachedBusyBuffer.RioBuffer.Length = (uint)_busyResponseBytes.Length; worker.cachedBusy = cachedBusyBuffer.RioBuffer; uint count; int ret; RIO_RESULT result; while (!_token.IsCancellationRequested) { _rio.Notify(cq); var sucess = GetQueuedCompletionStatus(completionPort, out bytes, out key, out overlapped, -1); if (sucess) { count = _rio.DequeueCompletion(cq, (IntPtr)results, maxResults); ret = _rio.Notify(cq); for (var i = 0; i < count; i++) { result = results[i]; if (result.RequestCorrelation == RIO.CachedValue) { // cached send response, don't release buffer } else if (result.RequestCorrelation < 0) { // first send 2 buffers are cached responses // so should next have a 0 for a send //worker.bufferPool.ReleaseBuffer((int)-result.RequestCorrelation); } else { // receive TcpConnection connection; if (worker.connections.TryGetValue(result.ConnectionCorrelation, out connection)) { connection.CompleteReceive(result.RequestCorrelation, result.BytesTransferred); } } } } else { var error = GetLastError(); if (error != 258) { throw new Exception(String.Format("ERROR: GetQueuedCompletionStatusEx returned {0}", error)); } } } cachedOKBuffer.Dispose(); cachedBusyBuffer.Dispose(); }