Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ConcurrentQueueSegment.cs
Go to the documentation of this file.
6
8
9[DebuggerDisplay("Capacity = {Capacity}")]
10internal sealed class ConcurrentQueueSegment<T>
11{
12 [StructLayout(LayoutKind.Auto)]
13 [DebuggerDisplay("Item = {Item}, SequenceNumber = {SequenceNumber}")]
14 internal struct Slot
15 {
16 public T Item;
17
18 public int SequenceNumber;
19 }
20
21 internal readonly Slot[] _slots;
22
23 internal readonly int _slotsMask;
24
26
28
29 internal bool _frozenForEnqueues;
30
32
33 internal int Capacity => _slots.Length;
34
35 internal int FreezeOffset => _slots.Length * 2;
36
37 internal ConcurrentQueueSegment(int boundedLength)
38 {
39 _slots = new Slot[boundedLength];
40 _slotsMask = boundedLength - 1;
41 for (int i = 0; i < _slots.Length; i++)
42 {
44 }
45 }
46
48 {
50 {
51 _frozenForEnqueues = true;
53 }
54 }
55
56 public bool TryDequeue([MaybeNullWhen(false)] out T item)
57 {
58 Slot[] slots = _slots;
59 SpinWait spinWait = default(SpinWait);
60 while (true)
61 {
62 int num = Volatile.Read(ref _headAndTail.Head);
63 int num2 = num & _slotsMask;
64 int num3 = Volatile.Read(ref slots[num2].SequenceNumber);
65 int num4 = num3 - (num + 1);
66 if (num4 == 0)
67 {
68 if (Interlocked.CompareExchange(ref _headAndTail.Head, num + 1, num) != num)
69 {
70 continue;
71 }
72 item = slots[num2].Item;
74 {
75 if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
76 {
77 slots[num2].Item = default(T);
78 }
79 Volatile.Write(ref slots[num2].SequenceNumber, num + slots.Length);
80 }
81 return true;
82 }
83 if (num4 < 0)
84 {
85 bool frozenForEnqueues = _frozenForEnqueues;
86 int num5 = Volatile.Read(ref _headAndTail.Tail);
87 if (num5 - num <= 0 || (frozenForEnqueues && num5 - FreezeOffset - num <= 0))
88 {
89 break;
90 }
91 spinWait.SpinOnce(-1);
92 }
93 }
94 item = default(T);
95 return false;
96 }
97
98 public bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
99 {
100 if (resultUsed)
101 {
104 }
105 Slot[] slots = _slots;
106 SpinWait spinWait = default(SpinWait);
107 while (true)
108 {
109 int num = Volatile.Read(ref _headAndTail.Head);
110 int num2 = num & _slotsMask;
111 int num3 = Volatile.Read(ref slots[num2].SequenceNumber);
112 int num4 = num3 - (num + 1);
113 if (num4 == 0)
114 {
115 result = (resultUsed ? slots[num2].Item : default(T));
116 return true;
117 }
118 if (num4 < 0)
119 {
120 bool frozenForEnqueues = _frozenForEnqueues;
121 int num5 = Volatile.Read(ref _headAndTail.Tail);
122 if (num5 - num <= 0 || (frozenForEnqueues && num5 - FreezeOffset - num <= 0))
123 {
124 break;
125 }
126 spinWait.SpinOnce(-1);
127 }
128 }
129 result = default(T);
130 return false;
131 }
132
133 public bool TryEnqueue(T item)
134 {
135 Slot[] slots = _slots;
136 while (true)
137 {
138 int num = Volatile.Read(ref _headAndTail.Tail);
139 int num2 = num & _slotsMask;
140 int num3 = Volatile.Read(ref slots[num2].SequenceNumber);
141 int num4 = num3 - num;
142 if (num4 == 0)
143 {
144 if (Interlocked.CompareExchange(ref _headAndTail.Tail, num + 1, num) == num)
145 {
146 slots[num2].Item = item;
147 Volatile.Write(ref slots[num2].SequenceNumber, num + 1);
148 return true;
149 }
150 }
151 else if (num4 < 0)
152 {
153 break;
154 }
155 }
156 return false;
157 }
158}
bool TryPeek([MaybeNullWhen(false)] out T result, bool resultUsed)
bool TryDequeue([MaybeNullWhen(false)] out T item)
static int CompareExchange(ref int location1, int value, int comparand)
static int Add(ref int location1, int value)
static bool Read(ref bool location)
Definition Volatile.cs:67
static void Write(ref bool location, bool value)
Definition Volatile.cs:74