三国卡牌客户端基础资源仓库
hch
4 天以前 cdac25a8e4f91a4663bf5f80994538dd263b757c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
 
using System;
using System.Threading;
 
namespace Cysharp.Threading.Tasks.Internal
{
    // Same interface as System.Buffers.ArrayPool<T> but only provides Shared.
 
    internal sealed class ArrayPool<T>
    {
        // Same size as System.Buffers.DefaultArrayPool<T>
        const int DefaultMaxNumberOfArraysPerBucket = 50;
 
        static readonly T[] EmptyArray = new T[0];
 
        public static readonly ArrayPool<T> Shared = new ArrayPool<T>();
 
        readonly MinimumQueue<T[]>[] buckets;
        readonly SpinLock[] locks;
 
        ArrayPool()
        {
            // see: GetQueueIndex
            buckets = new MinimumQueue<T[]>[18];
            locks = new SpinLock[18];
            for (int i = 0; i < buckets.Length; i++)
            {
                buckets[i] = new MinimumQueue<T[]>(4);
                locks[i] = new SpinLock(false);
            }
        }
 
        public T[] Rent(int minimumLength)
        {
            if (minimumLength < 0)
            {
                throw new ArgumentOutOfRangeException("minimumLength");
            }
            else if (minimumLength == 0)
            {
                return EmptyArray;
            }
 
            var size = CalculateSize(minimumLength);
            var index = GetQueueIndex(size);
            if (index != -1)
            {
                var q = buckets[index];
                var lockTaken = false;
                try
                {
                    locks[index].Enter(ref lockTaken);
 
                    if (q.Count != 0)
                    {
                        return q.Dequeue();
                    }
                }
                finally
                {
                    if (lockTaken) locks[index].Exit(false);
                }
            }
 
            return new T[size];
        }
 
        public void Return(T[] array, bool clearArray = false)
        {
            if (array == null || array.Length == 0)
            {
                return;
            }
 
            var index = GetQueueIndex(array.Length);
            if (index != -1)
            {
                if (clearArray)
                {
                    Array.Clear(array, 0, array.Length);
                }
 
                var q = buckets[index];
                var lockTaken = false;
 
                try
                {
                    locks[index].Enter(ref lockTaken);
 
                    if (q.Count > DefaultMaxNumberOfArraysPerBucket)
                    {
                        return;
                    }
 
                    q.Enqueue(array);
                }
                finally
                {
                    if (lockTaken) locks[index].Exit(false);
                }
            }
        }
 
        static int CalculateSize(int size)
        {
            size--;
            size |= size >> 1;
            size |= size >> 2;
            size |= size >> 4;
            size |= size >> 8;
            size |= size >> 16;
            size += 1;
 
            if (size < 8)
            {
                size = 8;
            }
 
            return size;
        }
 
        static int GetQueueIndex(int size)
        {
            switch (size)
            {
                case 8: return 0;
                case 16: return 1;
                case 32: return 2;
                case 64: return 3;
                case 128: return 4;
                case 256: return 5;
                case 512: return 6;
                case 1024: return 7;
                case 2048: return 8;
                case 4096: return 9;
                case 8192: return 10;
                case 16384: return 11;
                case 32768: return 12;
                case 65536: return 13;
                case 131072: return 14;
                case 262144: return 15;
                case 524288: return 16;
                case 1048576: return 17; // max array length
                default:
                    return -1;
            }
        }
    }
}