private void LargeAllocationProducesCorrectResults() { var byteRange = Enumerable.Range(0, 16384 + 64).Select(x => (byte)x).ToArray(); var expectedByteRange = byteRange.Concat(byteRange).ToArray(); var mem0 = MemoryPoolBlock2.Create(new ArraySegment <byte>(byteRange), IntPtr.Zero, null, null); var mem1 = MemoryPoolBlock2.Create(new ArraySegment <byte>(byteRange), IntPtr.Zero, null, null); mem0.End = byteRange.Length; mem1.End = byteRange.Length; mem0.Next = mem1; var begin = mem0.GetIterator(); var end = GetIterator(begin, expectedByteRange.Length); var s = begin.GetAsciiString(end); Assert.Equal(s.Length, expectedByteRange.Length); for (var i = 0; i < expectedByteRange.Length; i++) { var sb = (byte)s[i]; var b = expectedByteRange[i]; Assert.Equal(sb, b); } }
private void ProducingCompleteNoPreComplete(MemoryPoolIterator2 end) { MemoryPoolBlock2 blockToReturn = null; lock (_returnLock) { Debug.Assert(!_lastStart.IsDefault); // If the socket has been closed, return the produced blocks // instead of advancing the now non-existent tail. if (_tail != null) { _tail = end.Block; _tail.End = end.Index; } else { blockToReturn = _lastStart.Block; } _lastStart = default(MemoryPoolIterator2); } if (blockToReturn != null) { ThreadPool.QueueUserWorkItem(_returnBlocks, blockToReturn); } }
public void Put() { var blocks = new MemoryPoolBlock2[4]; for (var i = 0; i < 4; ++i) { blocks[i] = _pool.Lease(16); blocks[i].End += 16; for (var j = 0; j < blocks.Length; ++j) { blocks[i].Array[blocks[i].Start + j] = 0x00; } if (i != 0) { blocks[i - 1].Next = blocks[i]; } } // put FF at first block's head var head = blocks[0].GetIterator(); Assert.True(head.Put(0xFF)); // data is put at correct position Assert.Equal(0xFF, blocks[0].Array[blocks[0].Start]); Assert.Equal(0x00, blocks[0].Array[blocks[0].Start + 1]); // iterator is moved to next byte after put Assert.Equal(1, head.Index - blocks[0].Start); for (var i = 0; i < 14; ++i) { // move itr to the end of the block 0 head.Take(); } // write to the end of block 0 Assert.True(head.Put(0xFE)); Assert.Equal(0xFE, blocks[0].Array[blocks[0].End - 1]); Assert.Equal(0x00, blocks[1].Array[blocks[1].Start]); // put data across the block link Assert.True(head.Put(0xFD)); Assert.Equal(0xFD, blocks[1].Array[blocks[1].Start]); Assert.Equal(0x00, blocks[1].Array[blocks[1].Start + 1]); // paint every block head = blocks[0].GetIterator(); for (var i = 0; i < 64; ++i) { Assert.True(head.Put((byte)i), $"Fail to put data at {i}."); } // Can't put anything by the end Assert.False(head.Put(0xFF)); }
private MemoryPoolIterator2 BuildSample(string data) { var store = data.Select(c => (byte)c).ToArray(); var mem = MemoryPoolBlock2.Create(new ArraySegment <byte>(store), IntPtr.Zero, null, null); mem.End = store.Length; return(mem.GetIterator()); }
private static void ReturnBlocks(MemoryPoolBlock2 block) { while (block != null) { var returningBlock = block; block = returningBlock.Next; returningBlock.Pool?.Return(returningBlock); } }
private static void ReturnWrittenBlocks(MemoryPoolBlock2 block) { while (block != null) { var returnBlock = block; block = block.Next; returnBlock.Unpin(); returnBlock.Pool?.Return(returnBlock); } }
private void TestAllLengths(MemoryPoolBlock2 block, int lengths) { for (var firstIndex = 0; firstIndex <= lengths; ++firstIndex) { for (var lastIndex = firstIndex; lastIndex <= lengths; ++lastIndex) { var first = block.GetIterator().Add(firstIndex); var last = block.GetIterator().Add(lastIndex); Assert.Equal(firstIndex, block.GetIterator().GetLength(first)); Assert.Equal(lastIndex, block.GetIterator().GetLength(last)); Assert.Equal(lastIndex - firstIndex, first.GetLength(last)); } } }
public void IncomingComplete(int count, Exception error) { Action awaitableState; lock (_sync) { // Unpin may called without an earlier Pin if (_pinned != null) { _pinned.Unpin(); _pinned.End += count; if (_head == null) { _head = _tail = _pinned; } else if (_tail == _pinned) { // NO-OP: this was a read into unoccupied tail-space } else { _tail.Next = _pinned; _tail = _pinned; } } _pinned = null; if (count == 0) { RemoteIntakeFin = true; } if (error != null) { _awaitableError = error; } awaitableState = Interlocked.Exchange( ref _awaitableState, _awaitableIsCompleted); _manualResetEvent.Set(); } if (awaitableState != _awaitableIsCompleted && awaitableState != _awaitableIsNotCompleted) { Task.Run(awaitableState); } }
private void FullByteRangeSupported() { var byteRange = Enumerable.Range(0, 256).Select(x => (byte)x).ToArray(); var mem = MemoryPoolBlock2.Create(new ArraySegment <byte>(byteRange), IntPtr.Zero, null, null); mem.End = byteRange.Length; var begin = mem.GetIterator(); var end = GetIterator(begin, byteRange.Length); var s = begin.GetAsciiString(end); Assert.Equal(s.Length, byteRange.Length); for (var i = 0; i < byteRange.Length; i++) { var sb = (byte)s[i]; var b = byteRange[i]; Assert.Equal(sb, b); } }
// This is called on the libuv event loop private void ReturnAllBlocks() { lock (_returnLock) { var block = _head; while (block != _tail) { var returnBlock = block; block = block.Next; returnBlock.Pool?.Return(returnBlock); } // Only return the _tail if we aren't between ProducingStart/Complete calls if (_lastStart.IsDefault) { _tail.Pool?.Return(_tail); } _head = null; _tail = null; } }
public SocketOutput( KestrelThread thread, UvStreamHandle socket, MemoryPool2 memory, Connection connection, long connectionId, IKestrelTrace log, IThreadPool threadPool, Queue <UvWriteReq> writeReqPool) { _thread = thread; _socket = socket; _connection = connection; _connectionId = connectionId; _log = log; _threadPool = threadPool; _tasksPending = new Queue <TaskCompletionSource <object> >(_initialTaskQueues); _tasksCompleted = new Queue <TaskCompletionSource <object> >(_initialTaskQueues); _writeContextPool = new Queue <WriteContext>(_maxPooledWriteContexts); _writeReqPool = writeReqPool; _head = memory.Lease(); _tail = _head; }
public IncomingBuffer IncomingStart(int minimumSize) { lock (_sync) { if (_tail != null && minimumSize <= _tail.Data.Offset + _tail.Data.Count - _tail.End) { _pinned = _tail; var data = new ArraySegment <byte>(_pinned.Data.Array, _pinned.End, _pinned.Data.Offset + _pinned.Data.Count - _pinned.End); var dataPtr = _pinned.Pin(); return(new IncomingBuffer { Data = data, DataPtr = dataPtr, }); } } _pinned = _memory.Lease(minimumSize); return(new IncomingBuffer { Data = _pinned.Data, DataPtr = _pinned.Pin() }); }
public void ConsumingComplete( MemoryPoolIterator2 consumed, MemoryPoolIterator2 examined) { MemoryPoolBlock2 returnStart = null; MemoryPoolBlock2 returnEnd = null; lock (_sync) { if (!consumed.IsDefault) { returnStart = _head; returnEnd = consumed.Block; _head = consumed.Block; _head.Start = consumed.Index; } if (!examined.IsDefault && examined.IsEnd && RemoteIntakeFin == false && _awaitableError == null) { _manualResetEvent.Reset(); var awaitableState = Interlocked.CompareExchange( ref _awaitableState, _awaitableIsNotCompleted, _awaitableIsCompleted); } } while (returnStart != returnEnd) { var returnBlock = returnStart; returnStart = returnStart.Next; returnBlock.Pool?.Return(returnBlock); } }
public void ServerPipeListenForConnections() { var loop = new UvLoopHandle(_logger); var serverListenPipe = new UvPipeHandle(_logger); loop.Init(_uv); serverListenPipe.Init(loop, false); serverListenPipe.Bind(@"\\.\pipe\ServerPipeListenForConnections"); serverListenPipe.Listen(128, (_1, status, error, _2) => { var serverConnectionPipe = new UvPipeHandle(_logger); serverConnectionPipe.Init(loop, true); try { serverListenPipe.Accept(serverConnectionPipe); } catch (Exception) { serverConnectionPipe.Dispose(); return; } var writeRequest = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); writeRequest.Init(loop); var block = MemoryPoolBlock2.Create( new ArraySegment <byte>(new byte[] { 1, 2, 3, 4 }), dataPtr: IntPtr.Zero, pool: null, slab: null); var start = new MemoryPoolIterator2(block, 0); var end = new MemoryPoolIterator2(block, block.Data.Count); writeRequest.Write( serverConnectionPipe, start, end, 1, (_3, status2, error2, _4) => { writeRequest.Dispose(); serverConnectionPipe.Dispose(); serverListenPipe.Dispose(); block.Unpin(); }, null); }, null); var worker = new Thread(() => { var loop2 = new UvLoopHandle(_logger); var clientConnectionPipe = new UvPipeHandle(_logger); var connect = new UvConnectRequest(new KestrelTrace(new TestKestrelTrace())); loop2.Init(_uv); clientConnectionPipe.Init(loop2, true); connect.Init(loop2); connect.Connect(clientConnectionPipe, @"\\.\pipe\ServerPipeListenForConnections", (_1, status, error, _2) => { var buf = loop2.Libuv.buf_init(Marshal.AllocHGlobal(8192), 8192); connect.Dispose(); clientConnectionPipe.ReadStart( (_3, cb, _4) => buf, (_3, status2, _4) => { if (status2 == 0) { clientConnectionPipe.Dispose(); } }, null); }, null); loop2.Run(); loop2.Dispose(); }); worker.Start(); loop.Run(); loop.Dispose(); worker.Join(); }
public static async Task <MemoryPoolBlock2> CopyToAsync(this Stream source, Stream destination, MemoryPoolBlock2 block) { int bytesRead; while ((bytesRead = await source.ReadAsync(block.Array, block.Data.Offset, block.Data.Count)) != 0) { await destination.WriteAsync(block.Array, block.Data.Offset, bytesRead); } return(block); }
public async Task SocketCanReadAndWrite() { var loop = new UvLoopHandle(_logger); loop.Init(_uv); var tcp = new UvTcpHandle(_logger); tcp.Init(loop); var address = ServerAddress.FromUrl("http://localhost:54321/"); tcp.Bind(address); tcp.Listen(10, (_, status, error, state) => { Console.WriteLine("Connected"); var tcp2 = new UvTcpHandle(_logger); tcp2.Init(loop); tcp.Accept(tcp2); var data = Marshal.AllocCoTaskMem(500); tcp2.ReadStart( (a, b, c) => tcp2.Libuv.buf_init(data, 500), (__, nread, state2) => { if (nread <= 0) { tcp2.Dispose(); } else { for (var x = 0; x < 2; x++) { var req = new UvWriteReq(new KestrelTrace(new TestKestrelTrace())); req.Init(loop); var block = MemoryPoolBlock2.Create( new ArraySegment <byte>(new byte[] { 65, 66, 67, 68, 69 }), dataPtr: IntPtr.Zero, pool: null, slab: null); var start = new MemoryPoolIterator2(block, 0); var end = new MemoryPoolIterator2(block, block.Data.Count); req.Write( tcp2, start, end, 1, (_1, _2, _3, _4) => { block.Unpin(); }, null); } } }, null); tcp.Dispose(); }, null); Console.WriteLine("Task.Run"); var t = Task.Run(async() => { var socket = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); #if DNX451 await Task.Factory.FromAsync( socket.BeginConnect, socket.EndConnect, new IPEndPoint(IPAddress.Loopback, 54321), null, TaskCreationOptions.None); await Task.Factory.FromAsync( socket.BeginSend, socket.EndSend, new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) }, SocketFlags.None, null, TaskCreationOptions.None); #else await socket.ConnectAsync(new IPEndPoint(IPAddress.Loopback, 54321)); await socket.SendAsync(new[] { new ArraySegment <byte>(new byte[] { 1, 2, 3, 4, 5 }) }, SocketFlags.None); #endif socket.Shutdown(SocketShutdown.Send); var buffer = new ArraySegment <byte>(new byte[2048]); while (true) { #if DNX451 var count = await Task.Factory.FromAsync( socket.BeginReceive, socket.EndReceive, new[] { buffer }, SocketFlags.None, null, TaskCreationOptions.None); #else var count = await socket.ReceiveAsync(new[] { buffer }, SocketFlags.None); #endif Console.WriteLine("count {0} {1}", count, System.Text.Encoding.ASCII.GetString(buffer.Array, 0, count)); if (count <= 0) { break; } } socket.Dispose(); }); loop.Run(); loop.Dispose(); await t; }
public MemoryPoolIterator2 ProducingStart() { _producingBlock = _memory.Lease(); return(new MemoryPoolIterator2(_producingBlock)); }
private void AssertIterator(MemoryPoolIterator2 iter, MemoryPoolBlock2 block, int index) { Assert.Same(block, iter.Block); Assert.Equal(index, iter.Index); }