/// <inheritdoc />
        internal override MemoryGroup <T> AllocateGroup <T>(
            long totalLength,
            int bufferAlignment,
            AllocationOptions options = AllocationOptions.None)
        {
            long totalLengthInBytes = totalLength * Unsafe.SizeOf <T>();

            if (totalLengthInBytes <= this.sharedArrayPoolThresholdInBytes)
            {
                var buffer = new SharedArrayPoolBuffer <T>((int)totalLength);
                return(MemoryGroup <T> .CreateContiguous(buffer, options.Has(AllocationOptions.Clean)));
            }

            if (totalLengthInBytes <= this.poolBufferSizeInBytes)
            {
                // Optimized path renting single array from the pool
                UnmanagedMemoryHandle mem = this.pool.Rent();
                if (mem.IsValid)
                {
                    UnmanagedBuffer <T> buffer = this.pool.CreateGuardedBuffer <T>(mem, (int)totalLength, options.Has(AllocationOptions.Clean));
                    return(MemoryGroup <T> .CreateContiguous(buffer, options.Has(AllocationOptions.Clean)));
                }
            }

            // Attempt to rent the whole group from the pool, allocate a group of unmanaged buffers if the attempt fails:
            if (MemoryGroup <T> .TryAllocate(this.pool, totalLength, bufferAlignment, options, out MemoryGroup <T> poolGroup))
            {
                return(poolGroup);
            }

            return(MemoryGroup <T> .Allocate(this.nonPoolAllocator, totalLength, bufferAlignment, options));
        }
        /// <inheritdoc />
        public override IMemoryOwner <T> Allocate <T>(
            int length,
            AllocationOptions options = AllocationOptions.None)
        {
            Guard.MustBeGreaterThanOrEqualTo(length, 0, nameof(length));
            int lengthInBytes = length * Unsafe.SizeOf <T>();

            if (lengthInBytes <= this.sharedArrayPoolThresholdInBytes)
            {
                var buffer = new SharedArrayPoolBuffer <T>(length);
                if (options.Has(AllocationOptions.Clean))
                {
                    buffer.GetSpan().Clear();
                }

                return(buffer);
            }

            if (lengthInBytes <= this.poolBufferSizeInBytes)
            {
                UnmanagedMemoryHandle mem = this.pool.Rent();
                if (mem.IsValid)
                {
                    UnmanagedBuffer <T> buffer = this.pool.CreateGuardedBuffer <T>(mem, length, options.Has(AllocationOptions.Clean));
                    return(buffer);
                }
            }

            return(this.nonPoolAllocator.Allocate <T>(length, options));
        }
예제 #3
0
        public void Free_ClosesHandle()
        {
            var h = UnmanagedMemoryHandle.Allocate(128);

            h.Free();
            Assert.True(h.IsInvalid);
            Assert.Equal(IntPtr.Zero, h.Handle);
        }
예제 #4
0
        private protected UnmanagedMemoryManager(int length, bool zeroMem)
        {
            var size = UnmanagedMemoryHandle.SizeOf <T>(length);

            address = Marshal.AllocHGlobal(new IntPtr(size));
            GC.AddMemoryPressure(size);
            Length = length;
            if (zeroMem)
            {
                Runtime.InteropServices.Memory.ClearBits(address, size);
            }
            owner = true;
        }
        public UnmanagedBuffer <T> CreateGuardedBuffer <T>(
            UnmanagedMemoryHandle handle,
            int lengthInElements,
            bool clear)
            where T : struct
        {
            var buffer = new UnmanagedBuffer <T>(lengthInElements, new ReturnToPoolBufferLifetimeGuard(this, handle));

            if (clear)
            {
                buffer.Clear();
            }

            return(buffer);
        }
예제 #6
0
            static void RunTest(string countStr)
            {
                int countInner = int.Parse(countStr);
                var l          = new List <UnmanagedMemoryHandle>();

                for (int i = 0; i < countInner; i++)
                {
                    Assert.Equal(i, UnmanagedMemoryHandle.TotalOutstandingHandles);
                    var h = UnmanagedMemoryHandle.Allocate(42);
                    Assert.Equal(i + 1, UnmanagedMemoryHandle.TotalOutstandingHandles);
                    l.Add(h);
                }

                for (int i = 0; i < countInner; i++)
                {
                    Assert.Equal(countInner - i, UnmanagedMemoryHandle.TotalOutstandingHandles);
                    l[i].Free();
                    Assert.Equal(countInner - i - 1, UnmanagedMemoryHandle.TotalOutstandingHandles);
                }
            }
예제 #7
0
        public unsafe void Allocate_AllocatesReadWriteMemory()
        {
            var h = UnmanagedMemoryHandle.Allocate(128);

            Assert.False(h.IsInvalid);
            Assert.True(h.IsValid);
            byte *ptr = (byte *)h.Handle;

            for (int i = 0; i < 128; i++)
            {
                ptr[i] = (byte)i;
            }

            for (int i = 0; i < 128; i++)
            {
                Assert.Equal((byte)i, ptr[i]);
            }

            h.Free();
        }
 public ReturnToPoolBufferLifetimeGuard(UniformUnmanagedMemoryPool pool, UnmanagedMemoryHandle handle)
     : base(handle) =>
     this.pool = pool;
예제 #9
0
 public FreeHandle(UnmanagedMemoryHandle handle)
     : base(handle)
 {
 }
예제 #10
0
 protected UnmanagedBufferLifetimeGuard(UnmanagedMemoryHandle handle) => this.handle = handle;