Ejemplo n.º 1
0
        public void PinAddReferenceReleaseTest()
        {
            var array = new byte[1024];
            OwnedBuffer <byte> owned = array;
            var memory = owned.Buffer;

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

            Assert.True(owned.HasOutstandingReferences);
            h.Free();
            Assert.False(owned.HasOutstandingReferences);
        }
Ejemplo n.º 2
0
        public void PinAddReferenceReleaseTest()
        {
            var array = new byte[1024];
            OwnedBuffer <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);
        }
Ejemplo n.º 3
0
        public void TestThrowOnAccessAfterDipose()
        {
            var array = new byte[1024];
            OwnedBuffer <byte> owned = array;
            var span = owned.Span;

            Assert.Equal(array.Length, span.Length);

            owned.Dispose();

            Assert.Throws <ObjectDisposedException>(() => {
                var spanDisposed = owned.Span;
            });
        }
Ejemplo n.º 4
0
        public void DangerousTryGetArray()
        {
            var array = new byte[] { 1, 2, 3, 4, 5 };
            OwnedBuffer <byte>    owned  = array;
            ReadOnlyBuffer <byte> buffer = owned.ReadOnlyBuffer;

            Assert.True(buffer.DangerousTryGetArray(out var dangerousArray));
            Assert.Equal(array.Length, dangerousArray.Count);

            for (int i = dangerousArray.Offset; i < dangerousArray.Count + dangerousArray.Offset; i++)
            {
                Assert.Equal(array[i], dangerousArray.Array[i]);
            }
        }
Ejemplo n.º 5
0
        public void RacyAccess()
        {
            for (int k = 0; k < 1000; k++)
            {
                var owners           = new OwnedBuffer <byte> [128];
                var memories         = new Buffer <byte> [owners.Length];
                var reserves         = new DisposableReservation <byte> [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]   = array;
                    memories[i] = owners[i].Buffer;
                }

                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].Reserve();
                            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]);
                }
            }
        }
Ejemplo n.º 6
0
        static void Pin(OwnedBuffer <byte> buffer)
        {
            var memory = buffer.Buffer;

            Assert.False(buffer.IsRetained);
            var handle = memory.Pin();

            unsafe
            {
                Assert.NotEqual(0L, new IntPtr(handle.PinnedPointer).ToInt64());
            }
            Assert.True(buffer.IsRetained);
            handle.Dispose();
            Assert.False(buffer.IsRetained);
        }
Ejemplo n.º 7
0
        static void MemoryHandleDoubleFree(OwnedBuffer <byte> buffer)
        {
            var memory = buffer.Buffer;
            var handle = memory.Pin();

            Assert.True(buffer.IsRetained);
            buffer.Retain();
            Assert.True(buffer.IsRetained);
            handle.Dispose();
            Assert.True(buffer.IsRetained);
            handle.Dispose();
            Assert.True(buffer.IsRetained);
            buffer.Release();
            Assert.False(buffer.IsRetained);
        }
Ejemplo n.º 8
0
        public void ReservationPerformance(int number, int size, int threads, ReferenceCountingMethod m)
        {
            var iterations = 1000000;

            var o = ReferenceCountingSettings.OwnedMemory;

            ReferenceCountingSettings.OwnedMemory = m;

            Benchmark.Iterate(() => {
                var owners   = new OwnedBuffer <byte> [number];
                var memories = new Buffer <byte> [owners.Length];

                for (int i = 0; i < owners.Length; i++)
                {
                    owners[i]   = new AutoPooledMemory(size);
                    memories[i] = owners[i].Buffer;
                }

                var tasks = new List <Task>(threads);
                for (int t = 0; t < threads; t++)
                {
                    tasks.Add(Task.Run(() => {
                        for (int k = 0; k < iterations / owners.Length; k++)
                        {
                            for (int i = 0; i < owners.Length; i++)
                            {
                                using (var reserve = memories[i].Reserve()) {
                                    var s = reserve.Span;
                                    for (int j = 0; j < owners.Length; j++)
                                    {
                                        s[j] = (byte)1;
                                    }
                                }
                            }
                        }
                    }));
                }

                Task.WaitAll(tasks.ToArray());

                for (int i = 0; i < owners.Length; i++)
                {
                    owners[i].Release();
                }
            });

            ReferenceCountingSettings.OwnedMemory = o;
        }
Ejemplo n.º 9
0
        public Buffer(T[] array)
        {
            if (array == null)
            {
                BufferPrimitivesThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }
            if (default(T) == null && array.GetType() != typeof(T[]))
            {
                BufferPrimitivesThrowHelper.ThrowArrayTypeMismatchException(typeof(T));
            }

            _array  = array;
            _owner  = null;
            _index  = 0;
            _length = array.Length;
        }
Ejemplo n.º 10
0
        public ReadOnlyBuffer(T[] array, int start, int length)
        {
            if (array == null)
            {
                BufferPrimitivesThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }
            if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
            {
                BufferPrimitivesThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
            }

            _array  = array;
            _owner  = null;
            _index  = start;
            _length = length;
        }
Ejemplo n.º 11
0
        public void MemoryHandleDoubleFree()
        {
            var array = new byte[1024];
            OwnedBuffer <byte> owned = array;
            var memory = owned.Buffer;
            var h      = memory.Pin();

            Assert.True(owned.HasOutstandingReferences);
            owned.AddReference();
            Assert.True(owned.HasOutstandingReferences);
            h.Free();
            Assert.True(owned.HasOutstandingReferences);
            h.Free();
            Assert.True(owned.HasOutstandingReferences);
            owned.Release();
            Assert.False(owned.HasOutstandingReferences);
        }
Ejemplo n.º 12
0
        private void ResizeDb()
        {
            var oldData    = _scratchMemory.Span;
            var newScratch = _pool.Rent(_scratchMemory.Length * 2);
            int dbLength   = newScratch.Length / 2;

            var newDb = newScratch.Buffer.Slice(0, dbLength);

            _db.Slice(0, _valuesIndex).Span.CopyTo(newDb.Span);
            _db = newDb;

            var newStackMemory = newScratch.Buffer.Slice(dbLength);

            _stack.Resize(newStackMemory);
            _scratchManager.Dispose();
            _scratchManager = newScratch;
        }
Ejemplo n.º 13
0
        public void MemoryHandleDoubleFree()
        {
            var array = new byte[1024];
            OwnedBuffer <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);
        }
Ejemplo n.º 14
0
        // tests that OwnedBuffer.Buffer and OwnedBuffer.ReadOnlyBuffer point to the same memory
        static void Buffer(OwnedBuffer <byte> buffer)
        {
            var rwBuffer = buffer.Buffer;
            var rwSpan   = rwBuffer.Span;

            var roBuffer = buffer.ReadOnlyBuffer;
            var roSpan   = roBuffer.Span;

            Assert.Equal(roSpan.Length, rwSpan.Length);

            for (int i = 0; i < roSpan.Length; i++)
            {
                var  value    = roSpan[i];
                byte newValue = (byte)(value + 1);
                rwSpan[i] = newValue;
                Assert.Equal(newValue, roSpan[i]);
            }
        }
Ejemplo n.º 15
0
        public void ReleasedBlockWorks()
        {
            var pool  = new MemoryPool();
            var block = pool.Rent(1);

            block.Dispose();

            OwnedBuffer <byte> block2 = null;

            // Lease-return until we get same block
            do
            {
                block2?.Dispose();
                block2 = pool.Rent(1);
            } while (block != block2);

            Assert.True(block2.Span.Length > 0);
        }
Ejemplo n.º 16
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 memoryOffset = length;
                var dataOffset   = length * 2;
                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 OwnedBuffer and OwnedBuffer itself has offset relative to array
                var ownedBuffer = OwnedBuffer <byte> .Create(new ArraySegment <byte>(chars, memoryOffset, length * 3));

                var current = new BufferSegment(ownedBuffer, 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)));
        }
Ejemplo n.º 17
0
        public void SimpleTestS()
        {
            {
                var array = new byte[1024];
                OwnedBuffer <byte> owned = array;
                var span = owned.Span;
                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]);
            }
        }
Ejemplo n.º 18
0
        public BufferSegment(OwnedBuffer <byte> buffer, int start, int end)
        {
            _owned   = buffer;
            Start    = start;
            End      = end;
            ReadOnly = true;

            // For unowned buffers, we need to make a copy here so that the caller can
            // give up the give this buffer back to the caller
            var unowned = buffer as UnownedBuffer;

            if (unowned != null)
            {
                _owned = unowned.MakeCopy(start, end - start, out Start, out End);
            }

            _owned.AddReference();
            _buffer = _owned.Buffer;
        }
Ejemplo n.º 19
0
        /// <summary>
        /// Create a <see cref="ReadableBuffer"/> over an OwnedBuffer.
        /// </summary>
        public static ReadableBuffer Create(OwnedBuffer <byte> data, int offset, int length)
        {
            if (data == null)
            {
                PipelinesThrowHelper.ThrowArgumentNullException(ExceptionArgument.data);
            }

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

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

            return(CreateInternal(data, offset, length));
        }
Ejemplo n.º 20
0
        public Buffer(T[] array, int start, int length)
        {
            if (array == null)
            {
                BufferPrimitivesThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }
            if (default(T) == null && array.GetType() != typeof(T[]))
            {
                BufferPrimitivesThrowHelper.ThrowArrayTypeMismatchException(typeof(T));
            }
            if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start))
            {
                BufferPrimitivesThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start);
            }

            _array  = array;
            _owner  = null;
            _index  = start;
            _length = length;
        }
Ejemplo n.º 21
0
        public PreservedBuffer <T> PreserveBuffer(int length)
        {
            if (length <= _smallTreshhold)
            {
                if (_sharedBuffer == null)
                {
                    _sharedBuffer = BufferPool <T> .RentOwnedBuffer(this._sharedBufferSize, false);

                    // NB we must create a reference or the first PreservedBuffer could
                    // dispose _sharedBuffer on PreservedBuffer disposal.
                    _sharedBuffer.AddReference();
                    _sharedBufferOffset = 0;
                }
                var bufferSize = _sharedBuffer.Length;
                var newOffset  = _sharedBufferOffset + length;
                if (newOffset > bufferSize)
                {
                    // replace shared buffer, the old one will be disposed
                    // when all ReservedMemory views on it are disposed
                    var previous = _sharedBuffer;
                    _sharedBuffer = BufferPool <T> .RentOwnedBuffer(_sharedBufferSize, false);

                    _sharedBuffer.AddReference();
                    previous.Release();
                    _sharedBufferOffset = 0;
                    newOffset           = length;
                }
                var buffer = _sharedBuffer.Buffer.Slice(_sharedBufferOffset, length);

                _sharedBufferOffset = newOffset;
                return(new PreservedBuffer <T>(buffer));
            }
            // NB here we exclusively own the buffer and disposal of PreservedBuffer will cause
            // disposal and returning to pool of the ownedBuffer instance, unless references were added via
            // PreservedBuffer.Close() or PreservedBuffer.Buffer.Reserve()/Pin() methods
            var ownedBuffer = BufferPool <T> .RentOwnedBuffer(length, false);

            var buffer2 = ownedBuffer.Buffer.Slice(0, length);

            return(new PreservedBuffer <T>(buffer2));
        }
Ejemplo n.º 22
0
        public void ReleasedBlockWorks()
        {
            using (var pool = new MemoryPool())
            {
                var block1 = pool.Rent(1);
                block1.Retain();
                block1.Release();

                OwnedBuffer <byte> block2 = null;

                // Lease-return until we get same block
                while (block1 != block2)
                {
                    block2 = pool.Rent(1);
                    block2.Retain();
                    block2.Release();
                }

                Assert.True(block2.AsSpan().Length > 0);
            }
        }
Ejemplo n.º 23
0
        public void CanUseOwnedBufferBasedReadableBuffers()
        {
            var data = Encoding.ASCII.GetBytes("***abc|def|ghijk****"); // note sthe padding here - verifying that it is omitted correctly
            OwnedBuffer <byte> owned = 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());
            }
        }
Ejemplo n.º 24
0
        static void MemoryAccessBasics(OwnedBuffer <byte> buffer)
        {
            var span = buffer.AsSpan();

            span[10] = 10;

            Assert.Equal(buffer.Length, span.Length);
            Assert.Equal(10, span[10]);

            var memory = buffer.Buffer;

            Assert.Equal(buffer.Length, memory.Length);
            Assert.Equal(10, memory.Span[10]);

            var array = memory.ToArray();

            Assert.Equal(buffer.Length, array.Length);
            Assert.Equal(10, array[10]);

            Span <byte> copy = new byte[20];

            memory.Slice(10, 20).CopyTo(copy);
            Assert.Equal(10, copy[0]);
        }
Ejemplo n.º 25
0
 internal ReadOnlyBuffer(OwnedBuffer <T> owner, int index, int length)
 {
     _arrayOrOwnedBuffer = owner;
     _index  = index | (1 << 31); // Before using _index, check if _index < 0, then 'and' it with bitMask
     _length = length;
 }
Ejemplo n.º 26
0
        /// <summary>
        /// Writes a new buffer into the pipeline. The task returned by this operation only completes when the next
        /// Read has been queued, or the Reader has completed, since the buffer provided here needs to be kept alive
        /// until the matching Read finishes (because we don't have ownership tracking when working with unowned buffers)
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        // Called by the WRITER
        public async Task WriteAsync(OwnedBuffer <byte> buffer, CancellationToken cancellationToken)
        {
            // If Writing has stopped, why is the caller writing??
            if (Writing.Status != TaskStatus.WaitingForActivation)
            {
                throw new OperationCanceledException("Writing has ceased on this pipeline");
            }

            // If Reading has stopped, we cancel. We don't write unless there's a reader ready in this pipeline.
            if (Reading.Status != TaskStatus.WaitingForActivation)
            {
                throw new OperationCanceledException("Reading has ceased on this pipeline");
            }

            // Register for cancellation on this token for the duration of the write
            using (cancellationToken.Register(state => ((UnownedBufferReader)state).CancelWriter(), this))
            {
                // Wait for reading to start
                await ReadingStarted;

                // Cancel this task if this write is cancelled
                cancellationToken.ThrowIfCancellationRequested();

                // Allocate a new segment to hold the buffer being written.
                using (var segment = new BufferSegment(buffer))
                {
                    segment.End = buffer.Buffer.Length;

                    if (_head == null || _head.ReadableBytes == 0)
                    {
                        // Update the head to point to the head of the buffer.
                        _head = segment;
                    }
                    else if (_tail != null)
                    {
                        // Add this segment to the end of the chain
                        _tail.SetNext(segment);
                    }

                    // Always update tail to the buffer's tail
                    _tail = segment;

                    // Trigger the continuation
                    Complete();

                    // Wait for another read to come (or for the end of Reading, which will also trigger this gate to open) in before returning
                    await _readWaiting;

                    if (_head.ReadableBytes > 0)
                    {
                        // We need to preserve any buffers that haven't been consumed
                        _head = BufferSegment.Clone(new ReadCursor(_head), new ReadCursor(_tail, _tail?.End ?? 0), out _tail);
                    }
                    else
                    {
                        // Drop segement references before Dispose gets called on the segment
                        _head = _tail = null;
                    }
                }

                // Cancel this task if this write is cancelled
                cancellationToken.ThrowIfCancellationRequested();
            }
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Wraps a rented buffer and returns it to the shared pool on Dispose
 /// </summary>
 /// <param name="rentedBuffer">A buffer that was previously rented from the shared BufferPool</param>
 /// <param name="offset"></param>
 /// <param name="count"></param>
 public RentedBufferStream(OwnedBuffer <byte> rentedBuffer, int count) : base(GetSegment(rentedBuffer).Array, 0, count)
 {
     _rentedBuffer = rentedBuffer;
 }
Ejemplo n.º 28
0
        public JsonObject Parse(ReadOnlySpan <byte> utf8Json, BufferPool pool = null)
        {
            _pool = pool;
            if (_pool == null)
            {
                _pool = BufferPool.Default;
            }
            _scratchManager = _pool.Rent(utf8Json.Length * 4);
            _scratchMemory  = _scratchManager.Buffer;

            int dbLength = _scratchMemory.Length / 2;

            _db    = _scratchMemory.Slice(0, dbLength);
            _stack = new TwoStacks(_scratchMemory.Slice(dbLength));

            _values            = utf8Json;
            _insideObject      = 0;
            _insideArray       = 0;
            _tokenType         = 0;
            _valuesIndex       = 0;
            _dbIndex           = 0;
            _jsonStartIsObject = false;

            SkipWhitespace();

            _jsonStartIsObject = _values[_valuesIndex] == '{';

            int arrayItemsCount        = 0;
            int numberOfRowsForMembers = 0;

            while (Read())
            {
                var tokenType = _tokenType;
                switch (tokenType)
                {
                case JsonTokenType.ObjectStart:
                    AppendDbRow(JsonObject.JsonValueType.Object, _valuesIndex);
                    while (!_stack.TryPushObject(numberOfRowsForMembers))
                    {
                        ResizeDb();
                    }
                    numberOfRowsForMembers = 0;
                    break;

                case JsonTokenType.ObjectEnd:
                    _db.Span.Slice(FindLocation(_stack.ObjectStackCount - 1, true)).Write <int>(numberOfRowsForMembers);
                    numberOfRowsForMembers += _stack.PopObject();
                    break;

                case JsonTokenType.ArrayStart:
                    AppendDbRow(JsonObject.JsonValueType.Array, _valuesIndex);
                    while (!_stack.TryPushArray(arrayItemsCount))
                    {
                        ResizeDb();
                    }
                    arrayItemsCount = 0;
                    break;

                case JsonTokenType.ArrayEnd:
                    _db.Span.Slice(FindLocation(_stack.ArrayStackCount - 1, false)).Write <int>(arrayItemsCount);
                    arrayItemsCount = _stack.PopArray();
                    break;

                case JsonTokenType.Property:
                    ParsePropertyName();
                    ParseValue();
                    numberOfRowsForMembers++;
                    numberOfRowsForMembers++;
                    break;

                case JsonTokenType.Value:
                    ParseValue();
                    arrayItemsCount++;
                    numberOfRowsForMembers++;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            var result = new JsonObject(_values, _db.Slice(0, _dbIndex).Span, _pool, _scratchManager);

            _scratchManager = null;
            return(result);
        }
Ejemplo n.º 29
0
 internal JsonObject(ReadOnlySpan <byte> values, ReadOnlySpan <byte> db, BufferPool pool = null, OwnedBuffer <byte> dbMemory = null)
 {
     _db       = db;
     _values   = values;
     _pool     = pool;
     _dbMemory = dbMemory;
 }