Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
SingleProducerSingleConsumerQueue.cs
Go to the documentation of this file.
6using Internal;
7
9
10[DebuggerDisplay("Count = {Count}")]
13{
14 [StructLayout(LayoutKind.Sequential)]
15 private sealed class Segment
16 {
17 internal Segment _next;
18
19 internal readonly T[] _array;
20
22
23 internal Segment(int size)
24 {
25 _array = new T[size];
26 }
27 }
28
29 private struct SegmentState
30 {
32
33 internal volatile int _first;
34
35 internal int _lastCopy;
36
38
39 internal int _firstCopy;
40
41 internal volatile int _last;
42
44 }
45
47 {
49
51 public T[] Items
52 {
53 get
54 {
55 List<T> list = new List<T>();
56 foreach (T item in _queue)
57 {
58 list.Add(item);
59 }
60 return list.ToArray();
61 }
62 }
63
68 }
69
70 private volatile Segment _head;
71
72 private volatile Segment _tail;
73
74 public bool IsEmpty
75 {
76 get
77 {
78 Segment head = _head;
79 if (head._state._first != head._state._lastCopy)
80 {
81 return false;
82 }
83 if (head._state._first != head._state._last)
84 {
85 return false;
86 }
87 return head._next == null;
88 }
89 }
90
91 public int Count
92 {
93 get
94 {
95 int num = 0;
96 for (Segment segment = _head; segment != null; segment = segment._next)
97 {
98 int num2 = segment._array.Length;
99 int first;
100 int last;
101 do
102 {
103 first = segment._state._first;
104 last = segment._state._last;
105 }
106 while (first != segment._state._first);
107 num += (last - first) & (num2 - 1);
108 }
109 return num;
110 }
111 }
112
114 {
115 _head = (_tail = new Segment(32));
116 }
117
118 public void Enqueue(T item)
119 {
121 T[] array = segment._array;
122 int last = segment._state._last;
123 int num = (last + 1) & (array.Length - 1);
124 if (num != segment._state._firstCopy)
125 {
126 array[last] = item;
127 segment._state._last = num;
128 }
129 else
130 {
132 }
133 }
134
136 {
137 if (segment._state._firstCopy != segment._state._first)
138 {
139 segment._state._firstCopy = segment._state._first;
140 Enqueue(item);
141 return;
142 }
143 int num = _tail._array.Length << 1;
144 if (num > 16777216)
145 {
146 num = 16777216;
147 }
148 Segment segment2 = new Segment(num);
149 segment2._array[0] = item;
150 segment2._state._last = 1;
151 segment2._state._lastCopy = 1;
152 try
153 {
154 }
155 finally
156 {
158 _tail = segment2;
159 }
160 }
161
162 public bool TryDequeue([MaybeNullWhen(false)] out T result)
163 {
165 T[] array = segment._array;
166 int first = segment._state._first;
167 if (first != segment._state._lastCopy)
168 {
169 result = array[first];
170 array[first] = default(T);
171 segment._state._first = (first + 1) & (array.Length - 1);
172 return true;
173 }
174 return TryDequeueSlow(ref segment, ref array, out result);
175 }
176
177 private bool TryDequeueSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
178 {
179 if (segment._state._last != segment._state._lastCopy)
180 {
181 segment._state._lastCopy = segment._state._last;
182 return TryDequeue(out result);
183 }
184 if (segment._next != null && segment._state._first == segment._state._last)
185 {
186 segment = segment._next;
187 array = segment._array;
188 _head = segment;
189 }
190 int first = segment._state._first;
191 if (first == segment._state._last)
192 {
193 result = default(T);
194 return false;
195 }
196 result = array[first];
197 array[first] = default(T);
198 segment._state._first = (first + 1) & (segment._array.Length - 1);
199 segment._state._lastCopy = segment._state._last;
200 return true;
201 }
202
203 public bool TryPeek([MaybeNullWhen(false)] out T result)
204 {
206 T[] array = segment._array;
207 int first = segment._state._first;
208 if (first != segment._state._lastCopy)
209 {
210 result = array[first];
211 return true;
212 }
213 return TryPeekSlow(ref segment, ref array, out result);
214 }
215
216 private bool TryPeekSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
217 {
218 if (segment._state._last != segment._state._lastCopy)
219 {
220 segment._state._lastCopy = segment._state._last;
221 return TryPeek(out result);
222 }
223 if (segment._next != null && segment._state._first == segment._state._last)
224 {
225 segment = segment._next;
226 array = segment._array;
227 _head = segment;
228 }
229 int first = segment._state._first;
230 if (first == segment._state._last)
231 {
232 result = default(T);
233 return false;
234 }
235 result = array[first];
236 return true;
237 }
238
239 public bool TryDequeueIf(Predicate<T> predicate, [MaybeNullWhen(false)] out T result)
240 {
242 T[] array = segment._array;
243 int first = segment._state._first;
244 if (first != segment._state._lastCopy)
245 {
246 result = array[first];
247 if (predicate == null || predicate(result))
248 {
249 array[first] = default(T);
250 segment._state._first = (first + 1) & (array.Length - 1);
251 return true;
252 }
253 result = default(T);
254 return false;
255 }
256 return TryDequeueIfSlow(predicate, ref segment, ref array, out result);
257 }
258
259 private bool TryDequeueIfSlow(Predicate<T> predicate, ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
260 {
261 if (segment._state._last != segment._state._lastCopy)
262 {
263 segment._state._lastCopy = segment._state._last;
264 return TryDequeueIf(predicate, out result);
265 }
266 if (segment._next != null && segment._state._first == segment._state._last)
267 {
268 segment = segment._next;
269 array = segment._array;
270 _head = segment;
271 }
272 int first = segment._state._first;
273 if (first == segment._state._last)
274 {
275 result = default(T);
276 return false;
277 }
278 result = array[first];
279 if (predicate == null || predicate(result))
280 {
281 array[first] = default(T);
282 segment._state._first = (first + 1) & (segment._array.Length - 1);
283 segment._state._lastCopy = segment._state._last;
284 return true;
285 }
286 result = default(T);
287 return false;
288 }
289
290 public void Clear()
291 {
292 T result;
293 while (TryDequeue(out result))
294 {
295 }
296 }
297
299 {
300 for (Segment segment = _head; segment != null; segment = segment._next)
301 {
302 for (int pt = segment._state._first; pt != segment._state._last; pt = (pt + 1) & (segment._array.Length - 1))
303 {
304 yield return segment._array[pt];
305 }
306 }
307 }
308
313
315 {
316 lock (syncObj)
317 {
318 return Count;
319 }
320 }
321}
SingleProducerSingleConsumerQueue_DebugView(System.Threading.Tasks.SingleProducerSingleConsumerQueue< T > queue)
bool TryDequeueIfSlow(Predicate< T > predicate, ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
bool TryDequeueSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
bool TryPeekSlow(ref Segment segment, ref T[] array, [MaybeNullWhen(false)] out T result)
bool TryDequeueIf(Predicate< T > predicate, [MaybeNullWhen(false)] out T result)
static void Write(ref bool location, bool value)
Definition Volatile.cs:74
new IEnumerator< T > GetEnumerator()