예제 #1
0
        internal int SelectBucketIndex(int bufferSize)
        {
            Debug.Assert(bufferSize >= 0);

            var intUtil = Math.Max(0, (32 - IntUtil.NumberOfLeadingZeros(bufferSize - 1)) - _minBufferLengthPow2);

#if DEBUG
            // TODO remove this check after some usage, see if this is not the same on some edge case

            // bufferSize of 0 will underflow here, causing a huge
            // index which the caller will discard because it is not
            // within the bounds of the bucket array.
            uint bitsRemaining = ((uint)bufferSize - 1) >> _minBufferLengthPow2;

            int poolIndex = 0;
            if (bitsRemaining > 0xFFFF)
            {
                bitsRemaining >>= 16; poolIndex = 16;
            }
            if (bitsRemaining > 0xFF)
            {
                bitsRemaining >>= 8; poolIndex += 8;
            }
            if (bitsRemaining > 0xF)
            {
                bitsRemaining >>= 4; poolIndex += 4;
            }
            if (bitsRemaining > 0x3)
            {
                bitsRemaining >>= 2; poolIndex += 2;
            }
            if (bitsRemaining > 0x1)
            {
                bitsRemaining >>= 1; poolIndex += 1;
            }
            var manual = poolIndex + (int)bitsRemaining;

            Debug.Assert(manual == intUtil);
#endif
            return(intUtil);
        }
예제 #2
0
 public static int FindNextPositivePowerOfTwo(int value)
 {
     return(1 << (32 - IntUtil.NumberOfLeadingZeros(value - 1)));
 }
예제 #3
0
        public RetainableMemoryPool(Func <RetainableMemoryPool <T>, int, RetainableMemory <T> > factory, int minLength,
                                    int maxLength, int maxBuffersPerBucket, int maxBucketsToTry = 2, bool pin = false, bool rentAlwaysClean = false)
        {
            IsRentAlwaysClean = rentAlwaysClean;
            _factory          = factory;

            if (minLength <= 16)
            {
                minLength = 16;
            }

            _minBufferLengthPow2 = 32 - IntUtil.NumberOfLeadingZeros(minLength - 1);
            _minBufferLength     = 1 << _minBufferLengthPow2;

            if (maxBucketsToTry < 0)
            {
                maxBucketsToTry = 0;
            }
            if (maxBucketsToTry > 4)
            {
                maxBucketsToTry = 4;
            }

            _maxBucketsToTry = maxBucketsToTry;

            if (pin && !TypeHelper <T> .IsPinnable)
            {
                ThrowHelper.ThrowInvalidOperationException($"Type {typeof(T).Name} is not pinnable. Cannot create RetainableMemoryPool with pinnable option.");
            }

            _pin = pin;

            if (maxLength <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxLength));
            }
            if (maxBuffersPerBucket <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxBuffersPerBucket));
            }

            // Our bucketing algorithm has a min length of 2^4 and a max length of 2^30.
            // Constrain the actual max used to those values.
            const int maximumArrayLength = 0x40000000;

            if (maxLength > maximumArrayLength)
            {
                maxLength = maximumArrayLength;
            }
            else if (maxLength < minLength)
            {
                maxLength = minLength;
            }

            _maxBufferLength = maxLength;

            // Create the buckets.
            int poolId     = Id;
            int maxBuckets = SelectBucketIndex(maxLength);
            var buckets    = new Bucket[maxBuckets + 1];

            for (int i = 0; i < buckets.Length; i++)
            {
                buckets[i] = new Bucket(this, _factory, GetMaxSizeForBucket(i), maxBuffersPerBucket, poolId);
            }
            _buckets = buckets;

            lock (KnownPools)
            {
                // start from 2,
                // pool idx == 0 is always null which means a buffer is not from pool
                // pool idx == 1 means a buffer is from default pool, e.g. static array pool
                for (int i = 2; i < KnownPools.Length; i++)
                {
                    if (KnownPools[i] == null)
                    {
                        PoolIdx       = checked ((byte)i);
                        KnownPools[i] = this;
                        return;
                    }
                }
                ThrowHelper.ThrowInvalidOperationException("KnownPools slots exhausted. 254 pools ought to be enough for anybody.");
            }
        }
예제 #4
0
 public void LzcntNegative()
 {
     Assert.AreEqual(0, IntUtil.NumberOfLeadingZeros(-1));
     Console.WriteLine(IntUtil.NumberOfLeadingZeros(-1));
 }