Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ConcurrentStack.cs
Go to the documentation of this file.
5
7
8[DebuggerDisplay("Count = {Count}")]
11{
12 private sealed class Node
13 {
14 internal readonly T _value;
15
16 internal Node _next;
17
18 internal Node(T value)
19 {
20 _value = value;
21 _next = null;
22 }
23 }
24
25 private volatile Node _head;
26
27 public bool IsEmpty => _head == null;
28
29 public int Count
30 {
31 get
32 {
33 int num = 0;
34 for (Node node = _head; node != null; node = node._next)
35 {
36 num++;
37 }
38 return num;
39 }
40 }
41
42 bool ICollection.IsSynchronized => false;
43
44 object ICollection.SyncRoot
45 {
46 get
47 {
49 }
50 }
51
53 {
54 }
55
57 {
58 if (collection == null)
59 {
60 throw new ArgumentNullException("collection");
61 }
63 }
64
66 {
67 Node node = null;
68 foreach (T item in collection)
69 {
70 Node node2 = new Node(item);
71 node2._next = node;
72 node = node2;
73 }
74 _head = node;
75 }
76
77 public void Clear()
78 {
79 _head = null;
80 }
81
83 {
84 if (array == null)
85 {
86 throw new ArgumentNullException("array");
87 }
89 }
90
91 public void CopyTo(T[] array, int index)
92 {
93 if (array == null)
94 {
95 throw new ArgumentNullException("array");
96 }
97 ToList().CopyTo(array, index);
98 }
99
100 public void Push(T item)
101 {
102 Node node = new Node(item);
103 node._next = _head;
104 if (Interlocked.CompareExchange(ref _head, node, node._next) != node._next)
105 {
107 }
108 }
109
110 public void PushRange(T[] items)
111 {
112 if (items == null)
113 {
114 throw new ArgumentNullException("items");
115 }
116 PushRange(items, 0, items.Length);
117 }
118
119 public void PushRange(T[] items, int startIndex, int count)
120 {
122 if (count != 0)
123 {
124 Node node;
125 Node node2 = (node = new Node(items[startIndex]));
126 for (int i = startIndex + 1; i < startIndex + count; i++)
127 {
128 Node node3 = new Node(items[i]);
129 node3._next = node2;
130 node2 = node3;
131 }
132 node._next = _head;
133 if (Interlocked.CompareExchange(ref _head, node2, node._next) != node._next)
134 {
136 }
137 }
138 }
139
140 private void PushCore(Node head, Node tail)
141 {
142 SpinWait spinWait = default(SpinWait);
143 do
144 {
145 spinWait.SpinOnce(-1);
146 tail._next = _head;
147 }
148 while (Interlocked.CompareExchange(ref _head, head, tail._next) != tail._next);
149 if (CDSCollectionETWBCLProvider.Log.IsEnabled())
150 {
151 CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPushFailed(spinWait.Count);
152 }
153 }
154
155 private static void ValidatePushPopRangeInput(T[] items, int startIndex, int count)
156 {
157 if (items == null)
158 {
159 throw new ArgumentNullException("items");
160 }
161 if (count < 0)
162 {
164 }
165 int num = items.Length;
166 if (startIndex >= num || startIndex < 0)
167 {
169 }
170 if (num - count < startIndex)
171 {
173 }
174 }
175
177 {
178 Push(item);
179 return true;
180 }
181
182 public bool TryPeek([MaybeNullWhen(false)] out T result)
183 {
184 Node head = _head;
185 if (head == null)
186 {
187 result = default(T);
188 return false;
189 }
190 result = head._value;
191 return true;
192 }
193
194 public bool TryPop([MaybeNullWhen(false)] out T result)
195 {
196 Node head = _head;
197 if (head == null)
198 {
199 result = default(T);
200 return false;
201 }
202 if (Interlocked.CompareExchange(ref _head, head._next, head) == head)
203 {
204 result = head._value;
205 return true;
206 }
207 return TryPopCore(out result);
208 }
209
210 public int TryPopRange(T[] items)
211 {
212 if (items == null)
213 {
214 throw new ArgumentNullException("items");
215 }
216 return TryPopRange(items, 0, items.Length);
217 }
218
219 public int TryPopRange(T[] items, int startIndex, int count)
220 {
222 if (count == 0)
223 {
224 return 0;
225 }
227 int num = TryPopCore(count, out poppedHead);
228 if (num > 0)
229 {
231 }
232 return num;
233 }
234
235 private bool TryPopCore([MaybeNullWhen(false)] out T result)
236 {
237 if (TryPopCore(1, out var poppedHead) == 1)
238 {
239 result = poppedHead._value;
240 return true;
241 }
242 result = default(T);
243 return false;
244 }
245
247 {
248 SpinWait spinWait = default(SpinWait);
249 int num = 1;
250 Node head;
251 int i;
252 while (true)
253 {
254 head = _head;
255 if (head == null)
256 {
257 if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
258 {
259 CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count);
260 }
261 poppedHead = null;
262 return 0;
263 }
264 Node node = head;
265 for (i = 1; i < count; i++)
266 {
267 if (node._next == null)
268 {
269 break;
270 }
271 node = node._next;
272 }
273 if (Interlocked.CompareExchange(ref _head, node._next, head) == head)
274 {
275 break;
276 }
277 for (int j = 0; j < num; j++)
278 {
279 spinWait.SpinOnce(-1);
280 }
281 num = ((!spinWait.NextSpinWillYield) ? (num * 2) : Random.Shared.Next(1, 8));
282 }
283 if (count == 1 && CDSCollectionETWBCLProvider.Log.IsEnabled())
284 {
285 CDSCollectionETWBCLProvider.Log.ConcurrentStack_FastPopFailed(spinWait.Count);
286 }
287 poppedHead = head;
288 return i;
289 }
290
291 private static void CopyRemovedItems(Node head, T[] collection, int startIndex, int nodesCount)
292 {
293 Node node = head;
294 for (int i = startIndex; i < startIndex + nodesCount; i++)
295 {
296 collection[i] = node._value;
297 node = node._next;
298 }
299 }
300
302 {
303 return TryPop(out item);
304 }
305
306 public T[] ToArray()
307 {
308 Node head = _head;
309 if (head != null)
310 {
311 return ToList(head).ToArray();
312 }
313 return Array.Empty<T>();
314 }
315
316 private List<T> ToList()
317 {
318 return ToList(_head);
319 }
320
322 {
323 List<T> list = new List<T>();
324 while (curr != null)
325 {
326 list.Add(curr._value);
327 curr = curr._next;
328 }
329 return list;
330 }
331
333 {
334 return GetEnumerator(_head);
335 }
336
338 {
339 for (Node current = head; current != null; current = current._next)
340 {
341 yield return current._value;
342 }
343 }
344
346 {
347 return ((IEnumerable<T>)this).GetEnumerator();
348 }
349}
int TryPopRange(T[] items, int startIndex, int count)
bool TryPop([MaybeNullWhen(false)] out T result)
bool TryPeek([MaybeNullWhen(false)] out T result)
void InitializeFromCollection(IEnumerable< T > collection)
bool TryPopCore([MaybeNullWhen(false)] out T result)
int TryPopCore(int count, out Node poppedHead)
void PushRange(T[] items, int startIndex, int count)
ConcurrentStack(IEnumerable< T > collection)
static void CopyRemovedItems(Node head, T[] collection, int startIndex, int nodesCount)
void ICollection. CopyTo(Array array, int index)
static void ValidatePushPopRangeInput(T[] items, int startIndex, int count)
bool TryAdd(TKey key, TValue value)
static Random Shared
Definition Random.cs:633
static string ConcurrentCollection_SyncRoot_NotSupported
Definition SR.cs:58
static string ConcurrentStack_PushPopRange_CountOutOfRange
Definition SR.cs:80
static string ConcurrentStack_PushPopRange_StartOutOfRange
Definition SR.cs:84
static string ConcurrentStack_PushPopRange_InvalidCount
Definition SR.cs:82
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
void CopyTo(Array array, int index)