コード例 #1
0
        public int IndexOf(ref T element, int start, int count)
        {
            ValidateRegion(start, count);
            var end = start + count;

            if (SpanHelper.IsPrimitive <T>())
            {
                var defaultComparer = default(PrimitiveComparer <T>);
                for (int i = start; start < end; ++i)
                {
                    if (defaultComparer.Equals(ref this[i], ref element))
                    {
                        return(i);
                    }
                }
                return(-1);
            }
            else
            {
                WrapperEqualityComparer <T> .CreateDefault(out var defaultComparer);

                for (int i = start; start < end; ++i)
                {
                    if (defaultComparer.Equals(ref this[i], ref element))
                    {
                        return(i);
                    }
                }
                return(-1);
            }
        }
コード例 #2
0
 public unsafe void ResizeToAtLeast(ref RawBuffer buffer, int targetSize, int copyCount)
 {
     Debug.Assert(copyCount <= buffer.Length, "Can't copy more than the capacity of the buffer.");
     Debug.Assert(copyCount <= targetSize, "Can't copy more than the target size.");
     //Only do anything if the new size is actually different from the current size.
     targetSize = 1 << (SpanHelper.GetContainingPowerOf2(targetSize));
     if (buffer.Allocated)
     {
         DecomposeId(buffer.Id, out var powerIndex, out var slotIndex);
         var currentSize = 1 << powerIndex;
         if (currentSize != targetSize || pools[powerIndex].GetStartPointerForSlot(slotIndex) != buffer.Memory)
         {
             TakeAtLeast(targetSize, out var newBuffer);
             Buffer.MemoryCopy(buffer.Memory, newBuffer.Memory, buffer.Length, copyCount);
             pools[powerIndex].Return(slotIndex);
             buffer = newBuffer;
         }
         else
         {
             //While the allocation size is equal to the target size, the buffer might not be.
             //Fortunately, if the allocation stays the same size and the buffer start is at its original location, we can skip doing any work.
             //(With more work, you could expand *backwards*, we just didn't bother since this is exceptionally rare anyway.
             //The typed codepath doesn't bother doing this at all, and that's fine.)
             buffer.Length = targetSize;
         }
     }
     else
     {
         //Nothing to return or copy.
         TakeAtLeast(targetSize, out buffer);
     }
 }
コード例 #3
0
ファイル: BufferPool.cs プロジェクト: netdebug/bepuphysics2
 public unsafe void Resize(ref RawBuffer buffer, int targetSize, int copyCount)
 {
     Debug.Assert(copyCount <= buffer.Length, "Can't copy more than the capacity of the buffer.");
     Debug.Assert(copyCount <= targetSize, "Can't copy more than the target size.");
     //Only do anything if the new size is actually different from the current size.
     targetSize = 1 << (SpanHelper.GetContainingPowerOf2(targetSize));
     if (buffer.Allocated)
     {
         DecomposeId(buffer.Id, out var powerIndex, out var slotIndex);
         var currentSize = 1 << powerIndex;
         if (currentSize != targetSize)
         {
             Take(targetSize, out var newBuffer);
             Unsafe.CopyBlockUnaligned(newBuffer.Memory, buffer.Memory, (uint)copyCount);
             pools[powerIndex].Return(slotIndex);
             buffer = newBuffer;
         }
         else
         {
             //While the allocation size is equal to the target size, the buffer might not be.
             //Fortunately, if the allocation stays the same size, there's no work to be done.
             buffer.Length = targetSize;
         }
     }
     else
     {
         //Nothing to return or copy.
         Take(targetSize, out buffer);
     }
 }
コード例 #4
0
 /// <summary>
 /// Creates a new memory pool.
 /// </summary>
 /// <param name="memoryPoolSize">Size of the pool in elements.</param>
 public Allocator(long memoryPoolSize, int allocationCountEstimate = 128)
 {
     this.Capacity = memoryPoolSize;
     QuickDictionary <ulong, Allocation, Array <ulong>, Array <Allocation>, Array <int>, PrimitiveComparer <ulong> > .Create(
         new PassthroughArrayPool <ulong>(), new PassthroughArrayPool <Allocation>(), new PassthroughArrayPool <int>(),
         SpanHelper.GetContainingPowerOf2(allocationCountEstimate), 3, out allocations);
 }
コード例 #5
0
 public static int GetCapacityForCount <T>(int count)
 {
     if (count == 0)
     {
         count = 1;
     }
     return((1 << SpanHelper.GetContainingPowerOf2(count * Unsafe.SizeOf <T>())) / Unsafe.SizeOf <T>());
 }
コード例 #6
0
        public void Return(ref Array <T> array)
        {
            ValidateCount();
#if DEBUG
            Debug.Assert(outstandingResources.Remove(array.Memory), "The buffer being returned must come from this pool, and buffers should only be returned once.");
#endif
            pools[SpanHelper.GetContainingPowerOf2(array.Length)].Push(array.Memory);
            array = new Array <T>();
        }
コード例 #7
0
 public void CopyTo <TOtherSpan>(int sourceStart, ref TOtherSpan targetSpan, int targetStart, int count) where TOtherSpan : ISpan <T>
 {
     if (typeof(TOtherSpan) == typeof(Buffer <T>))
     {
         SpanHelper.Copy(ref this, sourceStart, ref Unsafe.As <TOtherSpan, Buffer <T> >(ref targetSpan), targetStart, count);
     }
     else if (typeof(TOtherSpan) == typeof(Array <T>))
     {
         SpanHelper.Copy(ref this, sourceStart, ref Unsafe.As <TOtherSpan, Array <T> >(ref targetSpan), targetStart, count);
     }
     else
     {
         SpanHelper.CopyFallback <T, Buffer <T>, TOtherSpan>(ref this, sourceStart, ref targetSpan, targetStart, count);
     }
 }
コード例 #8
0
            public PowerPool(int power, int minimumBlockSize, int expectedPooledCount)
            {
                Power                       = power;
                SuballocationSize           = 1 << power;
                BlockSize                   = Math.Max(SuballocationSize, minimumBlockSize);
                Slots                       = new ManagedIdPool(expectedPooledCount);
                SuballocationsPerBlock      = BlockSize / SuballocationSize;
                SuballocationsPerBlockShift = SpanHelper.GetContainingPowerOf2(SuballocationsPerBlock);
                SuballocationsPerBlockMask  = (1 << SuballocationsPerBlockShift) - 1;
                Blocks                      = new Block[1];
                BlockCount                  = 0;

#if DEBUG
                outstandingIds = new HashSet <int>();
#if LEAKDEBUG
                outstandingAllocators = new Dictionary <string, HashSet <int> >();
#endif
#endif
            }
コード例 #9
0
            public unsafe void Take(out RawBuffer buffer)
            {
                var slot       = Slots.Take();
                var blockIndex = slot >> SuballocationsPerBlockShift;

                if (blockIndex >= Blocks.Length)
                {
                    Array.Resize(ref Blocks, 1 << SpanHelper.GetContainingPowerOf2(blockIndex + 1));
                }
                if (blockIndex >= BlockCount)
                {
#if DEBUG
                    for (int i = 0; i < blockIndex; ++i)
                    {
                        Debug.Assert(Blocks[i].Allocated, "If a block index is found to exceed the current block count, then every block preceding the index should be allocated.");
                    }
#endif
                    BlockCount = blockIndex + 1;
                    Debug.Assert(!Blocks[blockIndex].Allocated);
                    Blocks[blockIndex] = new Block(BlockSize);
                }

                var indexInBlock = slot & SuballocationsPerBlockMask;
                buffer = new RawBuffer(Blocks[blockIndex].Allocate(indexInBlock, SuballocationSize), SuballocationSize, (Power << IdPowerShift) | slot);
                Debug.Assert(buffer.Id >= 0 && Power >= 0 && Power < 32, "Slot/power should be safely encoded in a 32 bit integer.");
#if DEBUG
                const int maximumOutstandingCapacity = 1 << 29;
                Debug.Assert(outstandingIds.Count * SuballocationSize <= maximumOutstandingCapacity,
                             $"Do you actually truly really need to have {maximumOutstandingCapacity} bytes taken from this power pool, or is this a memory leak?");
                Debug.Assert(outstandingIds.Add(slot), "Should not be able to request the same slot twice.");
#if LEAKDEBUG
                var allocator = new StackTrace().ToString();
                if (!outstandingAllocators.TryGetValue(allocator, out var idsForAllocator))
                {
                    idsForAllocator = new HashSet <int>();
                    outstandingAllocators.Add(allocator, idsForAllocator);
                }
                Debug.Assert(idsForAllocator.Count < (1 << 25), "Do you actually have that many allocations for this one allocator?");
                idsForAllocator.Add(slot);
#endif
#endif
            }
コード例 #10
0
 public unsafe void Resize(ref RawBuffer buffer, int targetSize, int copyCount)
 {
     //Only do anything if the new size is actually different from the current size.
     targetSize = 1 << (SpanHelper.GetContainingPowerOf2(targetSize));
     if (buffer.Length != targetSize) //Note that we don't check for allocated status- for buffers, a length of 0 is the same as being unallocated.
     {
         Take(targetSize, out var newBuffer);
         if (buffer.Length > 0)
         {
             //Don't bother copying from or re-pooling empty buffers. They're uninitialized.
             Debug.Assert(copyCount <= targetSize);
             Unsafe.CopyBlockUnaligned(newBuffer.Memory, buffer.Memory, (uint)copyCount);
             ReturnUnsafely(ref buffer);
         }
         else
         {
             Debug.Assert(copyCount == 0, "Should not be trying to copy elements from an empty span.");
         }
         buffer = newBuffer;
     }
 }
コード例 #11
0
 public unsafe void ReturnUnsafely(ref RawBuffer buffer)
 {
     ValidatePinnedState(true);
     pools[SpanHelper.GetContainingPowerOf2(buffer.Length)].Return(ref buffer);
 }
コード例 #12
0
 public void Take(int count, out RawBuffer buffer)
 {
     TakeForPower(SpanHelper.GetContainingPowerOf2(count), out buffer);
 }
コード例 #13
0
 /// <summary>
 /// Gets the capacity allocated for a power.
 /// </summary>
 /// <param name="power">Power to check.</param>
 /// <returns>Allocated capacity for the given power.</returns>
 public int GetCapacityForPower(int power)
 {
     SpanHelper.ValidatePower(power);
     return(pools[power].BlockCount * pools[power].BlockSize);
 }
コード例 #14
0
 /// <summary>
 /// Ensures that the pool associated with a given power has at least a certain amount of capacity, measured in bytes.
 /// </summary>
 /// <param name="byteCount">Minimum number of bytes to require for the power pool.</param>
 /// <param name="power">Power associated with the pool to check.</param>
 public void EnsureCapacityForPower(int byteCount, int power)
 {
     SpanHelper.ValidatePower(power);
     ValidatePinnedState(true);
     pools[power].EnsureCapacity(byteCount);
 }
コード例 #15
0
ファイル: Buffer.cs プロジェクト: LASTEXILE-CH/bepuphysics2
 public void CopyTo(int sourceStart, ref Buffer <T> target, int targetStart, int count)
 {
     SpanHelper.Copy(ref this, sourceStart, ref target, targetStart, count);
 }
コード例 #16
0
 public void Take(int count, out Array <T> span)
 {
     TakeForPower(SpanHelper.GetContainingPowerOf2(count), out span);;
 }