Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
LowLevelLifoSemaphore.cs
Go to the documentation of this file.
3using Internal;
4
5namespace System.Threading;
6
7internal sealed class LowLevelLifoSemaphore : IDisposable
8{
9 private struct Counts
10 {
11 private ulong _data;
12
13 public uint SignalCount
14 {
15 get
16 {
17 return GetUInt32Value(0);
18 }
19 set
20 {
22 }
23 }
24
25 public ushort WaiterCount => GetUInt16Value(32);
26
27 public byte SpinnerCount => GetByteValue(48);
28
30
31 private Counts(ulong data)
32 {
33 _data = data;
34 }
35
36 private uint GetUInt32Value(byte shift)
37 {
38 return (uint)(_data >> (int)shift);
39 }
40
41 private void SetUInt32Value(uint value, byte shift)
42 {
43 _data = (_data & ~(4294967295uL << (int)shift)) | ((ulong)value << (int)shift);
44 }
45
46 private ushort GetUInt16Value(byte shift)
47 {
48 return (ushort)(_data >> (int)shift);
49 }
50
51 private byte GetByteValue(byte shift)
52 {
53 return (byte)(_data >> (int)shift);
54 }
55
56 public void AddSignalCount(uint value)
57 {
58 _data += value;
59 }
60
62 {
63 _data--;
64 }
65
67 {
68 _data += 4294967296uL;
69 }
70
72 {
73 _data -= 4294967296uL;
74 }
75
77 {
78 Counts counts = new Counts(Interlocked.Add(ref _data, 18446744069414584320uL));
79 }
80
82 {
83 _data += 281474976710656uL;
84 }
85
87 {
88 _data -= 281474976710656uL;
89 }
90
92 {
93 uint num = (uint)(255 - CountOfWaitersSignaledToWake);
94 if (value > num)
95 {
96 value = num;
97 }
98 _data += (ulong)value << 56;
99 }
100
102 {
103 _data -= 72057594037927936uL;
104 }
105
106 public Counts InterlockedCompareExchange(Counts newCounts, Counts oldCounts)
107 {
108 return new Counts(Interlocked.CompareExchange(ref _data, newCounts._data, oldCounts._data));
109 }
110
111 public static bool operator ==(Counts lhs, Counts rhs)
112 {
113 return lhs._data == rhs._data;
114 }
115
116 public override bool Equals([NotNullWhen(true)] object obj)
117 {
118 if (obj is Counts counts)
119 {
120 return _data == counts._data;
121 }
122 return false;
123 }
124
125 public override int GetHashCode()
126 {
127 return (int)_data + (int)(_data >> 32);
128 }
129 }
130
132 {
133 private readonly PaddingFor32 _pad1;
134
136
137 private readonly PaddingFor32 _pad2;
138 }
139
141
142 private readonly int _maximumSignalCount;
143
144 private readonly int _spinCount;
145
146 private readonly Action _onWait;
147
149
150 public LowLevelLifoSemaphore(int initialSignalCount, int maximumSignalCount, int spinCount, Action onWait)
151 {
153 _separated._counts.SignalCount = (uint)initialSignalCount;
154 _maximumSignalCount = maximumSignalCount;
155 _spinCount = spinCount;
156 _onWait = onWait;
157 Create(maximumSignalCount);
158 }
159
160 public bool Wait(int timeoutMs, bool spinWait)
161 {
162 int num = (spinWait ? _spinCount : 0);
163 Counts counts = _separated._counts;
164 Counts newCounts;
165 while (true)
166 {
167 newCounts = counts;
168 if (counts.SignalCount != 0)
169 {
170 newCounts.DecrementSignalCount();
171 }
172 else if (timeoutMs != 0)
173 {
174 if (num > 0 && newCounts.SpinnerCount < byte.MaxValue)
175 {
176 newCounts.IncrementSpinnerCount();
177 }
178 else
179 {
180 newCounts.IncrementWaiterCount();
181 }
182 }
183 Counts counts2 = _separated._counts.InterlockedCompareExchange(newCounts, counts);
184 if (counts2 == counts)
185 {
186 break;
187 }
188 counts = counts2;
189 }
190 if (counts.SignalCount != 0)
191 {
192 return true;
193 }
194 if (newCounts.WaiterCount != counts.WaiterCount)
195 {
196 return WaitForSignal(timeoutMs);
197 }
198 if (timeoutMs == 0)
199 {
200 return false;
201 }
202 int processorCount = Environment.ProcessorCount;
203 int num2 = ((processorCount <= 1) ? 10 : 0);
204 while (num2 < num)
205 {
206 LowLevelSpinWaiter.Wait(num2, 10, processorCount);
207 num2++;
208 counts = _separated._counts;
209 while (counts.SignalCount != 0)
210 {
211 Counts newCounts2 = counts;
212 newCounts2.DecrementSignalCount();
213 newCounts2.DecrementSpinnerCount();
214 Counts counts3 = _separated._counts.InterlockedCompareExchange(newCounts2, counts);
215 if (counts3 == counts)
216 {
217 return true;
218 }
219 counts = counts3;
220 }
221 }
222 counts = _separated._counts;
223 while (true)
224 {
225 Counts newCounts3 = counts;
226 newCounts3.DecrementSpinnerCount();
227 if (counts.SignalCount != 0)
228 {
229 newCounts3.DecrementSignalCount();
230 }
231 else
232 {
233 newCounts3.IncrementWaiterCount();
234 }
235 Counts counts4 = _separated._counts.InterlockedCompareExchange(newCounts3, counts);
236 if (counts4 == counts)
237 {
238 break;
239 }
240 counts = counts4;
241 }
242 if (counts.SignalCount == 0)
243 {
244 return WaitForSignal(timeoutMs);
245 }
246 return true;
247 }
248
249 public void Release(int releaseCount)
250 {
251 Counts counts = _separated._counts;
252 int num;
253 while (true)
254 {
255 Counts newCounts = counts;
256 newCounts.AddSignalCount((uint)releaseCount);
257 num = (int)(Math.Min(newCounts.SignalCount, (uint)(counts.WaiterCount + counts.SpinnerCount)) - counts.SpinnerCount - counts.CountOfWaitersSignaledToWake);
258 if (num > 0)
259 {
260 if (num > releaseCount)
261 {
262 num = releaseCount;
263 }
264 newCounts.AddUpToMaxCountOfWaitersSignaledToWake((uint)num);
265 }
266 Counts counts2 = _separated._counts.InterlockedCompareExchange(newCounts, counts);
267 if (counts2 == counts)
268 {
269 break;
270 }
271 counts = counts2;
272 }
273 if (num > 0)
274 {
275 ReleaseCore(num);
276 }
277 }
278
279 private bool WaitForSignal(int timeoutMs)
280 {
281 _onWait();
282 Counts counts;
283 do
284 {
285 if (!WaitCore(timeoutMs))
286 {
288 return false;
289 }
290 counts = _separated._counts;
291 while (true)
292 {
293 Counts newCounts = counts;
294 if (counts.SignalCount != 0)
295 {
296 newCounts.DecrementSignalCount();
297 newCounts.DecrementWaiterCount();
298 }
299 if (counts.CountOfWaitersSignaledToWake != 0)
300 {
302 }
303 Counts counts2 = _separated._counts.InterlockedCompareExchange(newCounts, counts);
304 if (counts2 == counts)
305 {
306 break;
307 }
308 counts = counts2;
309 }
310 }
311 while (counts.SignalCount == 0);
312 return true;
313 }
314
315 private void Create(int maximumSignalCount)
316 {
319 {
320 int lastPInvokeError = Marshal.GetLastPInvokeError();
322 ex.HResult = lastPInvokeError;
323 throw ex;
324 }
325 }
326
328 {
330 {
331 Dispose();
332 }
333 }
334
335 public bool WaitCore(int timeoutMs)
336 {
337 int lpNumberOfBytes;
338 UIntPtr CompletionKey;
339 IntPtr lpOverlapped;
340 return Interop.Kernel32.GetQueuedCompletionStatus(_completionPort, out lpNumberOfBytes, out CompletionKey, out lpOverlapped, timeoutMs);
341 }
342
343 public void ReleaseCore(int count)
344 {
345 for (int i = 0; i < count; i++)
346 {
348 {
349 int lastPInvokeError = Marshal.GetLastPInvokeError();
351 ex.HResult = lastPInvokeError;
352 throw ex;
353 }
354 }
355 }
356
363}
static bool PostQueuedCompletionStatus(IntPtr CompletionPort, int dwNumberOfBytesTransferred, UIntPtr CompletionKey, IntPtr lpOverlapped)
static bool CloseHandle(IntPtr handle)
static bool GetQueuedCompletionStatus(IntPtr CompletionPort, out int lpNumberOfBytes, out UIntPtr CompletionKey, out IntPtr lpOverlapped, int dwMilliseconds)
static IntPtr CreateIoCompletionPort(IntPtr FileHandle, IntPtr ExistingCompletionPort, UIntPtr CompletionKey, int NumberOfConcurrentThreads)
static int ProcessorCount
static void SuppressFinalize(object obj)
Definition GC.cs:202
Definition GC.cs:8
static byte Min(byte val1, byte val2)
Definition Math.cs:912
static int CompareExchange(ref int location1, int value, int comparand)
static int Add(ref int location1, int value)
LowLevelLifoSemaphore(int initialSignalCount, int maximumSignalCount, int spinCount, Action onWait)
bool Wait(int timeoutMs, bool spinWait)
static readonly IntPtr Zero
Definition IntPtr.cs:18
override bool Equals([NotNullWhen(true)] object obj)
Counts InterlockedCompareExchange(Counts newCounts, Counts oldCounts)
static bool operator==(Counts lhs, Counts rhs)
static void Wait(int spinIndex, int sleep0Threshold, int processorCount)
static readonly UIntPtr Zero
Definition UIntPtr.cs:19