예제 #1
0
        public void ArrayMemoryLifetime()
        {
            Memory <byte> copyStoredForLater;
            var           owner = new OwnedArray <byte>(1024);

            try {
                Memory <byte> memory      = owner.Memory;
                Memory <byte> memorySlice = memory.Slice(10);
                copyStoredForLater = memorySlice;
                var r = memorySlice.Reserve();
                try {                                                 // increments the "outstanding span" refcount
                    Assert.Throws <InvalidOperationException>(() => { // memory is reserved; cannot dispose
                        owner.Dispose();
                    });
                    Assert.Throws <ObjectDisposedException>(() => {
                        Span <byte> span = memorySlice.Span;
                        span[0]          = 255;
                    });
                }
                finally {
                    Assert.Throws <ObjectDisposedException>(() => {
                        r.Dispose(); // releases the refcount
                    });
                }
            }
            finally {
                Assert.Throws <InvalidOperationException>(() => {
                    owner.Dispose();
                });
            }
            Assert.Throws <ObjectDisposedException>(() => { // manager is disposed
                var span = copyStoredForLater.Span;
            });
        }
예제 #2
0
        public void Create_WorksWithOwnedMemory()
        {
            var memory         = new OwnedArray <byte>(new byte[] { 1, 2, 3, 4, 5 });
            var readableBuffer = new ReadOnlyBuffer <byte>(memory, 2, 3);

            Assert.Equal(new byte[] { 3, 4, 5 }, readableBuffer.ToArray());
        }
예제 #3
0
        public void ArrayMemoryLifetime()
        {
            var array = new byte[1024];
            OwnedArray <byte> owned = array;

            TestLifetime(owned);
        }
예제 #4
0
        public void RacyAccess()
        {
            for (int k = 0; k < 1000; k++)
            {
                var owners           = new IMemoryOwner <byte> [128];
                var memories         = new Memory <byte> [owners.Length];
                var reserves         = new MemoryHandle[owners.Length];
                var disposeSuccesses = new bool[owners.Length];
                var reserveSuccesses = new bool[owners.Length];

                for (int i = 0; i < owners.Length; i++)
                {
                    var array = new byte[1024];
                    owners[i]   = new OwnedArray <byte>(array);
                    memories[i] = owners[i].Memory;
                }

                var dispose_task = Task.Run(() =>
                {
                    for (int i = 0; i < owners.Length; i++)
                    {
                        try
                        {
                            owners[i].Dispose();
                            disposeSuccesses[i] = true;
                        }
                        catch (InvalidOperationException)
                        {
                            disposeSuccesses[i] = false;
                        }
                    }
                });

                var reserve_task = Task.Run(() =>
                {
                    for (int i = owners.Length - 1; i >= 0; i--)
                    {
                        try
                        {
                            reserves[i]         = memories[i].Pin();
                            reserveSuccesses[i] = true;
                        }
                        catch (ObjectDisposedException)
                        {
                            reserveSuccesses[i] = false;
                        }
                    }
                });

                Task.WaitAll(reserve_task, dispose_task);

                for (int i = 0; i < owners.Length; i++)
                {
                    Assert.False(disposeSuccesses[i] && reserveSuccesses[i]);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Create a <see cref="ReadableBuffer"/> over an array.
        /// </summary>
        public static ReadableBuffer Create(byte[] data)
        {
            if (data == null)
            {
                PipelinesThrowHelper.ThrowArgumentNullException(ExceptionArgument.data);
            }

            OwnedMemory <byte> buffer = new OwnedArray <byte>(data);

            return(CreateInternal(buffer, 0, data.Length));
        }
예제 #6
0
        WeakReference LeakHandle()
        {
            // Creates an object that is both Pinned with a MemoryHandle,
            // and has a weak reference.
            var array = new byte[1024];
            OwnedArray <byte> owned = array;
            var memory = owned.Buffer;

            memory.Pin();
            return(new WeakReference(array));
        }
예제 #7
0
        public HttpResponse(int size)
        {
            var headersArray = ArrayPool <byte> .Shared.Rent(size / 2);

            _headersMemory = new OwnedArray <byte>(headersArray);
            _headers       = new ReadWriteBytes(_headersMemory.Memory);

            var bodyArray = ArrayPool <byte> .Shared.Rent(size / 2);

            _bodyMemory = new OwnedArray <byte>(bodyArray);
            _body       = new ReadWriteBytes(_bodyMemory.Memory);
        }
예제 #8
0
        public void PinAddReferenceReleaseTest()
        {
            var array = new byte[1024];
            OwnedArray <byte> owned = array;
            var memory = owned.Buffer;

            Assert.False(owned.IsRetained);
            var h = memory.Pin();

            Assert.True(owned.IsRetained);
            h.Dispose();
            Assert.False(owned.IsRetained);
        }
예제 #9
0
 protected override DisposableReservation Reserve(ref ReadOnlyMemory <byte> memory)
 {
     if (memory.Length < Length)
     {
         var copy = memory.Span.ToArray();
         OwnedArray <byte> newOwned = copy;
         memory = newOwned.Memory;
         return(memory.Reserve());
     }
     else
     {
         return(base.Reserve(ref memory));
     }
 }
예제 #10
0
        protected virtual void ProcessRequest(TcpConnection socket)
        {
            Log.LogVerbose("Processing Request");

            var requestBuffer = s_pool.Rent(RequestBufferSize);
            var arrayMemory   = new OwnedArray <byte>(requestBuffer);

            var requestByteCount = socket.Receive(requestBuffer);

            if (requestByteCount == 0)
            {
                socket.Close();
                return;
            }

            var requestMemory = arrayMemory.Memory.Slice(0, requestByteCount);
            var requestBytes  = new ReadOnlyBytes(requestMemory);

            var request = HttpRequest.Parse(requestBytes);

            Log.LogRequest(request);

            using (var response = new HttpResponse(1024))
            {
                WriteResponse(request, response);
                s_pool.Return(requestBuffer);

                Position position = Position.First;
                while (response.Headers.TryGet(ref position, out var headersSegment, true))
                {
                    socket.Send(headersSegment.Slice(0, response.HeadersLength));
                }

                position = Position.First;
                while (response.Body.TryGet(ref position, out var bodySegment))
                {
                    socket.Send(bodySegment.Slice(0, response.BodyLength));
                }

                socket.Close();
            }

            if (Log.IsVerbose)
            {
                Log.LogMessage(Log.Level.Verbose, "Request Processed and Response Sent", DateTime.UtcNow.Ticks);
            }
        }
예제 #11
0
        public void MemoryHandleDoubleFree()
        {
            var array = new byte[1024];
            OwnedArray <byte> owned = array;
            var memory = owned.Buffer;
            var h      = memory.Pin();

            Assert.True(owned.IsRetained);
            owned.Retain();
            Assert.True(owned.IsRetained);
            h.Dispose();
            Assert.True(owned.IsRetained);
            h.Dispose();
            Assert.True(owned.IsRetained);
            owned.Release();
            Assert.False(owned.IsRetained);
        }
예제 #12
0
        public void SimpleTestS()
        {
            {
                var array = new byte[1024];
                OwnedArray <byte> owned = array;
                var span = owned.AsSpan();
                span[10] = 10;
                Assert.Equal(10, array[10]);

                var memory        = owned.Buffer;
                var toArrayResult = memory.ToArray();
                Assert.Equal(owned.Length, array.Length);
                Assert.Equal(10, toArrayResult[10]);

                Span <byte> copy = new byte[20];
                memory.Slice(10, 20).CopyTo(copy);
                Assert.Equal(10, copy[0]);
            }
        }
예제 #13
0
        public static ReadableBuffer CreateBuffer(params byte[][] inputs)
        {
            if (inputs == null || inputs.Length == 0)
            {
                throw new InvalidOperationException();
            }

            var i = 0;

            BufferSegment last  = null;
            BufferSegment first = null;

            do
            {
                var s          = inputs[i];
                var length     = s.Length;
                var dataOffset = length;
                var chars      = new byte[length * 8];

                for (int j = 0; j < length; j++)
                {
                    chars[dataOffset + j] = s[j];
                }

                // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array
                var ownedBuffer = new OwnedArray <byte>(chars);
                var current     = new BufferSegment();
                current.SetMemory(ownedBuffer, length, length * 2);
                if (first == null)
                {
                    first = current;
                    last  = current;
                }
                else
                {
                    last.SetNext(current);
                    last = current;
                }
                i++;
            } while (i < inputs.Length);

            return(new ReadableBuffer(new ReadCursor(first, first.Start), new ReadCursor(last, last.Start + last.ReadableBytes)));
        }
예제 #14
0
        public ReadableBuffer CreateBuffer(params string[] inputs)
        {
            if (inputs == null || !inputs.Any())
            {
                throw new InvalidOperationException();
            }
            var i = 0;

            BufferSegment last  = null;
            BufferSegment first = null;

            do
            {
                var s            = inputs[i];
                var length       = s.Length;
                var memoryOffset = length;
                var dataOffset   = length * 2;
                var chars        = new byte[length * 8];

                for (int j = 0; j < length; j++)
                {
                    chars[dataOffset + j] = (byte)s[j];
                }

                // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array
                var ownedMemory = new OwnedArray <byte>(new ArraySegment <byte>(chars, memoryOffset, length * 3));
                var current     = new BufferSegment(ownedMemory, length, length * 2);
                if (first == null)
                {
                    first = current;
                    last  = current;
                }
                else
                {
                    last.Next = current;
                    last      = current;
                }
                i++;
            } while (i < inputs.Length);

            return(new ReadableBuffer(new ReadCursor(first, first.Start), new ReadCursor(last, last.Start + last.ReadableBytes)));
        }
예제 #15
0
        public static ReadOnlySequence <T> CreateBuffer <T>(params T[][] inputs) where T : struct
        {
            if (inputs == null || inputs.Length == 0)
            {
                throw new InvalidOperationException();
            }

            BufferSegment <T> last  = null;
            BufferSegment <T> first = null;

            for (int i = 0; i < inputs.Length; i++)
            {
                T[] source     = inputs[i];
                int length     = source.Length;
                int dataOffset = length;

                // Shift the incoming data for testing
                T[] chars = new T[length * 8];
                for (int j = 0; j < length; j++)
                {
                    chars[dataOffset + j] = source[j];
                }

                // Create a segment that has offset relative to the OwnedMemory and OwnedMemory itself has offset relative to array
                var ownedBuffer = new OwnedArray <T>(chars);
                var current     = new BufferSegment <T>();
                current.SetMemory(ownedBuffer, length, length * 2);
                if (first == null)
                {
                    first = current;
                    last  = current;
                }
                else
                {
                    last.SetNext(current);
                    last = current;
                }
            }

            return(new ReadOnlySequence <T>(first, 0, last, last.Length));
        }
예제 #16
0
        public void CanUseOwnedBufferBasedReadableBuffers()
        {
            var data = Encoding.ASCII.GetBytes("***abc|def|ghijk****"); // note sthe padding here - verifying that it is omitted correctly
            OwnedMemory <byte> owned = new OwnedArray <byte>(data);
            var buffer = ReadableBuffer.Create(owned, 3, data.Length - 7);

            Assert.Equal(13, buffer.Length);
            var split = buffer.Split((byte)'|');

            Assert.Equal(3, split.Count());
            using (var iter = split.GetEnumerator())
            {
                Assert.True(iter.MoveNext());
                var current = iter.Current;
                Assert.Equal("abc", current.GetAsciiString());
                using (var preserved = iter.Current.Preserve())
                {
                    Assert.Equal("abc", preserved.Buffer.GetAsciiString());
                }

                Assert.True(iter.MoveNext());
                current = iter.Current;
                Assert.Equal("def", current.GetAsciiString());
                using (var preserved = iter.Current.Preserve())
                {
                    Assert.Equal("def", preserved.Buffer.GetAsciiString());
                }

                Assert.True(iter.MoveNext());
                current = iter.Current;
                Assert.Equal("ghijk", current.GetAsciiString());
                using (var preserved = iter.Current.Preserve())
                {
                    Assert.Equal("ghijk", preserved.Buffer.GetAsciiString());
                }

                Assert.False(iter.MoveNext());
            }
        }
예제 #17
0
        public static ReadOnlySequence <T> CreateSplitBuffer <T>(T[] buffer, int minSize, int maxSize) where T : struct
        {
            if (buffer == null || buffer.Length == 0 || minSize <= 0 || maxSize <= 0 || minSize > maxSize)
            {
                throw new InvalidOperationException();
            }

            Random r = new Random(0xFEED);

            BufferSegment <T> last  = null;
            BufferSegment <T> first = null;
            var ownedBuffer         = new OwnedArray <T>(buffer);

            int remaining = buffer.Length;
            int position  = 0;

            while (remaining > 0)
            {
                int take = Math.Min(r.Next(minSize, maxSize), remaining);
                BufferSegment <T> current = new BufferSegment <T>();
                current.SetMemory(ownedBuffer, position, position + take);
                if (first == null)
                {
                    first = current;
                    last  = current;
                }
                else
                {
                    last.SetNext(current);
                    last = current;
                }
                remaining -= take;
                position  += take;
            }

            return(new ReadOnlySequence <T>(first, 0, last, last.Length));
        }
예제 #18
0
        /// <summary>
        /// Create a <see cref="ReadableBuffer"/> over an array.
        /// </summary>
        public static ReadableBuffer Create(byte[] data, int offset, int length)
        {
            if (data == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.data);
            }

            if (offset < 0)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset);
            }

            if (length < 0 || (offset + length) > data.Length)
            {
                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
            }

            var buffer  = new OwnedArray <byte>(data);
            var segment = new BufferSegment(buffer);

            segment.Start = offset;
            segment.End   = offset + length;
            return(new ReadableBuffer(new ReadCursor(segment, offset), new ReadCursor(segment, offset + length)));
        }
예제 #19
0
        public void ArrayMemoryLifetime()
        {
            var owner = new OwnedArray <byte>(1024);

            TestLifetime(owner);
        }