Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ConcurrentQueue.cs
Go to the documentation of this file.
6
8
9[DebuggerDisplay("Count = {Count}")]
12{
13 private readonly object _crossSegmentLock;
14
16
18
19 bool ICollection.IsSynchronized => false;
20
21 object ICollection.SyncRoot
22 {
23 get
24 {
25 ThrowHelper.ThrowNotSupportedException(ExceptionResource.ConcurrentCollection_SyncRoot_NotSupported);
26 return null;
27 }
28 }
29
30 public bool IsEmpty
31 {
32 get
33 {
34 T result;
35 return !TryPeek(out result, resultUsed: false);
36 }
37 }
38
39 public int Count
40 {
41 get
42 {
43 SpinWait spinWait = default(SpinWait);
46 int num;
47 int num2;
48 int num3;
49 int num4;
50 while (true)
51 {
52 head = _head;
53 tail = _tail;
54 num = Volatile.Read(ref head._headAndTail.Head);
55 num2 = Volatile.Read(ref head._headAndTail.Tail);
56 if (head == tail)
57 {
58 if (head == _head && tail == _tail && num == Volatile.Read(ref head._headAndTail.Head) && num2 == Volatile.Read(ref head._headAndTail.Tail))
59 {
60 return GetCount(head, num, num2);
61 }
62 }
63 else if (head._nextSegment == tail)
64 {
65 num3 = Volatile.Read(ref tail._headAndTail.Head);
66 num4 = Volatile.Read(ref tail._headAndTail.Tail);
67 if (head == _head && tail == _tail && num == Volatile.Read(ref head._headAndTail.Head) && num2 == Volatile.Read(ref head._headAndTail.Tail) && num3 == Volatile.Read(ref tail._headAndTail.Head) && num4 == Volatile.Read(ref tail._headAndTail.Tail))
68 {
69 break;
70 }
71 }
72 else
73 {
75 {
76 if (head == _head && tail == _tail)
77 {
78 int num5 = Volatile.Read(ref tail._headAndTail.Head);
79 int num6 = Volatile.Read(ref tail._headAndTail.Tail);
80 if (num == Volatile.Read(ref head._headAndTail.Head) && num2 == Volatile.Read(ref head._headAndTail.Tail) && num5 == Volatile.Read(ref tail._headAndTail.Head) && num6 == Volatile.Read(ref tail._headAndTail.Tail))
81 {
82 int num7 = GetCount(head, num, num2) + GetCount(tail, num5, num6);
83 for (ConcurrentQueueSegment<T> nextSegment = head._nextSegment; nextSegment != tail; nextSegment = nextSegment._nextSegment)
84 {
85 num7 += nextSegment._headAndTail.Tail - nextSegment.FreezeOffset;
86 }
87 return num7;
88 }
89 }
90 }
91 }
92 spinWait.SpinOnce();
93 }
94 return GetCount(head, num, num2) + GetCount(tail, num3, num4);
95 }
96 }
97
99 {
100 _crossSegmentLock = new object();
102 }
103
105 {
106 if (collection == null)
107 {
109 }
110 _crossSegmentLock = new object();
111 int num = 32;
112 if (collection is ICollection<T> { Count: var count } && count > num)
113 {
114 num = (int)Math.Min(BitOperations.RoundUpToPowerOf2((uint)count), 1048576u);
115 }
117 foreach (T item in collection)
118 {
119 Enqueue(item);
120 }
121 }
122
124 {
125 if (array is T[] array2)
126 {
128 return;
129 }
130 if (array == null)
131 {
133 }
134 ToArray().CopyTo(array, index);
135 }
136
138 {
139 return ((IEnumerable<T>)this).GetEnumerator();
140 }
141
143 {
144 Enqueue(item);
145 return true;
146 }
147
149 {
150 return TryDequeue(out item);
151 }
152
153 public T[] ToArray()
154 {
156 long count = GetCount(head, headHead, tail, tailTail);
157 T[] array = new T[count];
158 using IEnumerator<T> enumerator = Enumerate(head, headHead, tail, tailTail);
159 int num = 0;
160 while (enumerator.MoveNext())
161 {
162 array[num++] = enumerator.Current;
163 }
164 return array;
165 }
166
167 private static int GetCount(ConcurrentQueueSegment<T> s, int head, int tail)
168 {
169 if (head != tail && head != tail - s.FreezeOffset)
170 {
171 head &= s._slotsMask;
172 tail &= s._slotsMask;
173 if (head >= tail)
174 {
175 return s._slots.Length - head + tail;
176 }
177 return tail - head;
178 }
179 return 0;
180 }
181
183 {
184 long num = 0L;
185 int num2 = ((head == tail) ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
186 if (headHead < num2)
187 {
188 headHead &= head._slotsMask;
189 num2 &= head._slotsMask;
190 num += ((headHead < num2) ? (num2 - headHead) : (head._slots.Length - headHead + num2));
191 }
192 if (head != tail)
193 {
194 for (ConcurrentQueueSegment<T> nextSegment = head._nextSegment; nextSegment != tail; nextSegment = nextSegment._nextSegment)
195 {
196 num += nextSegment._headAndTail.Tail - nextSegment.FreezeOffset;
197 }
198 num += tailTail - tail.FreezeOffset;
199 }
200 return num;
201 }
202
203 public void CopyTo(T[] array, int index)
204 {
205 if (array == null)
206 {
208 }
209 if (index < 0)
210 {
212 }
214 long count = GetCount(head, headHead, tail, tailTail);
215 if (index > array.Length - count)
216 {
217 ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_ArrayPlusOffTooSmall);
218 }
219 int num = index;
220 using IEnumerator<T> enumerator = Enumerate(head, headHead, tail, tailTail);
221 while (enumerator.MoveNext())
222 {
223 array[num++] = enumerator.Current;
224 }
225 }
226
228 {
230 return Enumerate(head, headHead, tail, tailTail);
231 }
232
234 {
236 {
237 head = _head;
238 tail = _tail;
240 while (true)
241 {
242 concurrentQueueSegment._preservedForObservation = true;
243 if (concurrentQueueSegment == tail)
244 {
245 break;
246 }
248 }
249 tail.EnsureFrozenForEnqueues();
250 headHead = Volatile.Read(ref head._headAndTail.Head);
251 tailTail = Volatile.Read(ref tail._headAndTail.Tail);
252 }
253 }
254
256 {
257 int num = (i + 1) & segment._slotsMask;
258 if ((segment._slots[i].SequenceNumber & segment._slotsMask) != num)
259 {
260 SpinWait spinWait = default(SpinWait);
261 while ((Volatile.Read(ref segment._slots[i].SequenceNumber) & segment._slotsMask) != num)
262 {
263 spinWait.SpinOnce();
264 }
265 }
266 return segment._slots[i].Item;
267 }
268
270 {
271 int headTail = ((head == tail) ? tailTail : Volatile.Read(ref head._headAndTail.Tail)) - head.FreezeOffset;
272 if (headHead < headTail)
273 {
274 headHead &= head._slotsMask;
275 headTail &= head._slotsMask;
276 if (headHead < headTail)
277 {
278 for (int l = headHead; l < headTail; l++)
279 {
280 yield return GetItemWhenAvailable(head, l);
281 }
282 }
283 else
284 {
285 for (int l = headHead; l < head._slots.Length; l++)
286 {
287 yield return GetItemWhenAvailable(head, l);
288 }
289 for (int l = 0; l < headTail; l++)
290 {
291 yield return GetItemWhenAvailable(head, l);
292 }
293 }
294 }
295 if (head == tail)
296 {
297 yield break;
298 }
299 for (ConcurrentQueueSegment<T> s = head._nextSegment; s != tail; s = s._nextSegment)
300 {
301 int l = s._headAndTail.Tail - s.FreezeOffset;
302 for (int j = 0; j < l; j++)
303 {
304 yield return GetItemWhenAvailable(s, j);
305 }
306 }
307 tailTail -= tail.FreezeOffset;
308 for (int l = 0; l < tailTail; l++)
309 {
310 yield return GetItemWhenAvailable(tail, l);
311 }
312 }
313
314 public void Enqueue(T item)
315 {
316 if (!_tail.TryEnqueue(item))
317 {
319 }
320 }
321
322 private void EnqueueSlow(T item)
323 {
324 while (true)
325 {
327 if (tail.TryEnqueue(item))
328 {
329 break;
330 }
332 {
333 if (tail == _tail)
334 {
335 tail.EnsureFrozenForEnqueues();
336 int boundedLength = (tail._preservedForObservation ? 32 : Math.Min(tail.Capacity * 2, 1048576));
337 _tail = (tail._nextSegment = new ConcurrentQueueSegment<T>(boundedLength));
338 }
339 }
340 }
341 }
342
343 public bool TryDequeue([MaybeNullWhen(false)] out T result)
344 {
346 if (head.TryDequeue(out result))
347 {
348 return true;
349 }
350 if (head._nextSegment == null)
351 {
352 result = default(T);
353 return false;
354 }
355 return TryDequeueSlow(out result);
356 }
357
358 private bool TryDequeueSlow([MaybeNullWhen(false)] out T item)
359 {
360 while (true)
361 {
363 if (head.TryDequeue(out item))
364 {
365 return true;
366 }
367 if (head._nextSegment == null)
368 {
369 item = default(T);
370 return false;
371 }
372 if (head.TryDequeue(out item))
373 {
374 break;
375 }
377 {
378 if (head == _head)
379 {
380 _head = head._nextSegment;
381 }
382 }
383 }
384 return true;
385 }
386
387 public bool TryPeek([MaybeNullWhen(false)] out T result)
388 {
389 return TryPeek(out result, resultUsed: true);
390 }
391
392 private bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
393 {
395 while (true)
396 {
398 if (concurrentQueueSegment.TryPeek(out result, resultUsed))
399 {
400 return true;
401 }
402 if (concurrentQueueSegment2 != null)
403 {
405 }
406 else if (Volatile.Read(ref concurrentQueueSegment._nextSegment) == null)
407 {
408 break;
409 }
410 }
411 result = default(T);
412 return false;
413 }
414
415 public void Clear()
416 {
418 {
419 _tail.EnsureFrozenForEnqueues();
421 }
422 }
423}
bool TryPeek([MaybeNullWhen(false)] out T result)
void SnapForObservation(out ConcurrentQueueSegment< T > head, out int headHead, out ConcurrentQueueSegment< T > tail, out int tailTail)
bool TryDequeue([MaybeNullWhen(false)] out T result)
volatile ConcurrentQueueSegment< T > _tail
static int GetCount(ConcurrentQueueSegment< T > s, int head, int tail)
void ICollection. CopyTo(Array array, int index)
volatile ConcurrentQueueSegment< T > _head
bool TryDequeueSlow([MaybeNullWhen(false)] out T item)
static IEnumerator< T > Enumerate(ConcurrentQueueSegment< T > head, int headHead, ConcurrentQueueSegment< T > tail, int tailTail)
static T GetItemWhenAvailable(ConcurrentQueueSegment< T > segment, int i)
bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
static long GetCount(ConcurrentQueueSegment< T > head, int headHead, ConcurrentQueueSegment< T > tail, int tailTail)
bool TryAdd(TKey key, TValue value)
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static uint RoundUpToPowerOf2(uint value)
static bool Read(ref bool location)
Definition Volatile.cs:67
static void ThrowNotSupportedException(ExceptionResource resource)
static void ThrowArgumentOutOfRangeException(System.ExceptionArgument argument)
static void ThrowArgumentNullException(string name)
static void ThrowArgumentException(ExceptionResource resource)
void CopyTo(Array array, int index)