Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ConfigurableArrayPool.cs
Go to the documentation of this file.
3
4namespace System.Buffers;
5
6internal sealed class ConfigurableArrayPool<T> : ArrayPool<T>
7{
8 private sealed class Bucket
9 {
10 internal readonly int _bufferLength;
11
12 private readonly T[][] _buffers;
13
14 private readonly int _poolId;
15
16 private SpinLock _lock;
17
18 private int _index;
19
20 internal int Id => GetHashCode();
21
22 internal Bucket(int bufferLength, int numberOfBuffers, int poolId)
23 {
25 _buffers = new T[numberOfBuffers][];
26 _bufferLength = bufferLength;
27 _poolId = poolId;
28 }
29
30 internal T[] Rent()
31 {
32 T[][] buffers = _buffers;
33 T[] array = null;
34 bool lockTaken = false;
35 bool flag = false;
36 try
37 {
38 _lock.Enter(ref lockTaken);
39 if (_index < buffers.Length)
40 {
42 buffers[_index++] = null;
43 flag = array == null;
44 }
45 }
46 finally
47 {
48 if (lockTaken)
49 {
50 _lock.Exit(useMemoryBarrier: false);
51 }
52 }
53 if (flag)
54 {
55 array = new T[_bufferLength];
57 if (log.IsEnabled())
58 {
60 }
61 }
62 return array;
63 }
64
65 internal void Return(T[] array)
66 {
67 if (array.Length != _bufferLength)
68 {
70 }
71 bool lockTaken = false;
72 bool flag;
73 try
74 {
75 _lock.Enter(ref lockTaken);
76 flag = _index != 0;
77 if (flag)
78 {
80 }
81 }
82 finally
83 {
84 if (lockTaken)
85 {
86 _lock.Exit(useMemoryBarrier: false);
87 }
88 }
89 if (!flag)
90 {
92 if (log.IsEnabled())
93 {
95 }
96 }
97 }
98 }
99
100 private readonly Bucket[] _buckets;
101
102 private int Id => GetHashCode();
103
105 : this(1048576, 50)
106 {
107 }
108
109 internal ConfigurableArrayPool(int maxArrayLength, int maxArraysPerBucket)
110 {
111 if (maxArrayLength <= 0)
112 {
113 throw new ArgumentOutOfRangeException("maxArrayLength");
114 }
115 if (maxArraysPerBucket <= 0)
116 {
117 throw new ArgumentOutOfRangeException("maxArraysPerBucket");
118 }
119 if (maxArrayLength > 1073741824)
120 {
121 maxArrayLength = 1073741824;
122 }
123 else if (maxArrayLength < 16)
124 {
125 maxArrayLength = 16;
126 }
127 int id = Id;
128 int num = Utilities.SelectBucketIndex(maxArrayLength);
129 Bucket[] array = new Bucket[num + 1];
130 for (int i = 0; i < array.Length; i++)
131 {
132 array[i] = new Bucket(Utilities.GetMaxSizeForBucket(i), maxArraysPerBucket, id);
133 }
134 _buckets = array;
135 }
136
137 public override T[] Rent(int minimumLength)
138 {
139 if (minimumLength < 0)
140 {
141 throw new ArgumentOutOfRangeException("minimumLength");
142 }
143 if (minimumLength == 0)
144 {
145 return Array.Empty<T>();
146 }
148 int num = Utilities.SelectBucketIndex(minimumLength);
149 T[] array;
150 if (num < _buckets.Length)
151 {
152 int num2 = num;
153 do
154 {
155 array = _buckets[num2].Rent();
156 if (array != null)
157 {
158 if (log.IsEnabled())
159 {
160 log.BufferRented(array.GetHashCode(), array.Length, Id, _buckets[num2].Id);
161 }
162 return array;
163 }
164 }
165 while (++num2 < _buckets.Length && num2 != num + 2);
166 array = new T[_buckets[num]._bufferLength];
167 }
168 else
169 {
170 array = new T[minimumLength];
171 }
172 if (log.IsEnabled())
173 {
174 int hashCode = array.GetHashCode();
175 log.BufferRented(hashCode, array.Length, Id, -1);
176 log.BufferAllocated(hashCode, array.Length, Id, -1, (num >= _buckets.Length) ? ArrayPoolEventSource.BufferAllocatedReason.OverMaximumSize : ArrayPoolEventSource.BufferAllocatedReason.PoolExhausted);
177 }
178 return array;
179 }
180
181 public override void Return(T[] array, bool clearArray = false)
182 {
183 if (array == null)
184 {
185 throw new ArgumentNullException("array");
186 }
187 if (array.Length == 0)
188 {
189 return;
190 }
191 int num = Utilities.SelectBucketIndex(array.Length);
192 bool flag = num < _buckets.Length;
193 if (flag)
194 {
195 if (clearArray)
196 {
198 }
199 _buckets[num].Return(array);
200 }
202 if (log.IsEnabled())
203 {
204 int hashCode = array.GetHashCode();
205 log.BufferReturned(hashCode, array.Length, Id);
206 if (!flag)
207 {
208 log.BufferDropped(hashCode, array.Length, Id, -1, ArrayPoolEventSource.BufferDroppedReason.Full);
209 }
210 }
211 }
212}
static unsafe void Clear(Array array)
Definition Array.cs:755
unsafe void BufferRented(int bufferId, int bufferSize, int poolId, int bucketId)
unsafe void BufferDropped(int bufferId, int bufferSize, int poolId, int bucketId, BufferDroppedReason reason)
void BufferReturned(int bufferId, int bufferSize, int poolId)
static readonly ArrayPoolEventSource Log
unsafe void BufferAllocated(int bufferId, int bufferSize, int poolId, int bucketId, BufferAllocatedReason reason)
Bucket(int bufferLength, int numberOfBuffers, int poolId)
ConfigurableArrayPool(int maxArrayLength, int maxArraysPerBucket)
override void Return(T[] array, bool clearArray=false)
override T[] Rent(int minimumLength)
static int GetMaxSizeForBucket(int binIndex)
Definition Utilities.cs:22
static int SelectBucketIndex(int bufferSize)
Definition Utilities.cs:16
static string ArgumentException_BufferNotFromPool
Definition SR.cs:916
Definition SR.cs:7
void Enter(ref bool lockTaken)
Definition SpinLock.cs:94