public async Task PassthroughIfAllFlushesAreAwaited() { using (var slabPool = new SlabMemoryPool()) using (var diagnosticPool = new DiagnosticMemoryPool(slabPool)) { var pipeWriterFlushTcsArray = new[] { new TaskCompletionSource <FlushResult>(TaskCreationOptions.RunContinuationsAsynchronously), new TaskCompletionSource <FlushResult>(TaskCreationOptions.RunContinuationsAsynchronously), }; var sync = new object(); var mockPipeWriter = new MockPipeWriter(pipeWriterFlushTcsArray); var concurrentPipeWriter = new ConcurrentPipeWriter(mockPipeWriter, diagnosticPool, sync); ValueTask <FlushResult> flushTask; lock (sync) { var memory = concurrentPipeWriter.GetMemory(); Assert.Equal(1, mockPipeWriter.GetMemoryCallCount); concurrentPipeWriter.Advance(memory.Length); Assert.Equal(1, mockPipeWriter.AdvanceCallCount); flushTask = concurrentPipeWriter.FlushAsync(); Assert.Equal(1, mockPipeWriter.FlushCallCount); pipeWriterFlushTcsArray[0].SetResult(default);
public TransportThread(IoUringOptions options) { int res = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK); if (res == -1) { throw new ErrnoException(errno); } _eventfd = res; // Pin buffer for eventfd reads via io_uring byte[] bytes = new byte[8]; _eventfdBytes = GCHandle.Alloc(bytes, GCHandleType.Pinned); // Pin iovec used for eventfd reads via io_uring var eventfdIoVec = new iovec { iov_base = (void *)_eventfdBytes.AddrOfPinnedObject(), iov_len = bytes.Length }; _eventfdIoVecHandle = GCHandle.Alloc(eventfdIoVec, GCHandleType.Pinned); _eventfdIoVec = (iovec *)_eventfdIoVecHandle.AddrOfPinnedObject(); var memoryPool = new SlabMemoryPool(); _threadContext = new TransportThreadContext(options, memoryPool, _eventfd, s => Read(s), s => Write(s)); _maxBufferSize = memoryPool.MaxBufferSize; }