示例#1
0
        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);
            }
        }
示例#2
0
        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);
            }
        }
示例#3
0
        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));
        }
示例#4
0
        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());
        }
示例#5
0
        private static void ReturnBlocks(MemoryPoolBlock2 block)
        {
            while (block != null)
            {
                var returningBlock = block;
                block = returningBlock.Next;

                returningBlock.Pool?.Return(returningBlock);
            }
        }
示例#6
0
            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));
         }
     }
 }
示例#8
0
        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);
            }
        }
示例#9
0
        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);
            }
        }
示例#10
0
        // 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;
            }
        }
示例#11
0
        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;
        }
示例#12
0
        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()
            });
        }
示例#13
0
        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);
            }
        }
示例#14
0
        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;
        }
示例#17
0
 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);
 }