Terraria v1.4.4.9
Terraria source code documentation
Loading...
Searching...
No Matches
ReaderWriterLock.cs
Go to the documentation of this file.
4
5namespace System.Threading;
6
8{
9 [Serializable]
11 {
13 : base(System.SR.Format(message, System.SR.Format(System.SR.ExceptionFromHResult, errorHResult)))
14 {
16 }
17
22 }
23
24 private sealed class ThreadLocalLockEntry
25 {
28
29 private long _lockID;
30
32
33 public ushort _readerLevel;
34
35 public bool IsFree => _readerLevel == 0;
36
37 private ThreadLocalLockEntry(long lockID)
38 {
39 _lockID = lockID;
40 }
41
42 public static ThreadLocalLockEntry GetCurrent(long lockID)
43 {
46 {
47 if (threadLocalLockEntry2._lockID == lockID)
48 {
49 if (!threadLocalLockEntry2.IsFree)
50 {
52 }
53 return null;
54 }
55 }
56 return null;
57 }
58
59 public static ThreadLocalLockEntry GetOrCreateCurrent(long lockID)
60 {
62 if (threadLocalLockEntry != null)
63 {
64 if (threadLocalLockEntry._lockID == lockID)
65 {
67 }
68 if (threadLocalLockEntry.IsFree)
69 {
72 }
73 }
75 }
76
78 {
82 if (headEntry != null)
83 {
84 if (headEntry.IsFree)
85 {
87 }
89 for (ThreadLocalLockEntry next = headEntry._next; next != null; next = next._next)
90 {
91 if (next._lockID == lockID)
92 {
95 break;
96 }
97 if (threadLocalLockEntry3 == null && next.IsFree)
98 {
101 }
103 }
104 }
105 if (threadLocalLockEntry == null)
106 {
107 if (threadLocalLockEntry3 != null)
108 {
110 if (threadLocalLockEntry2 == null)
111 {
113 }
116 }
117 else
118 {
120 }
121 }
125 }
126 }
127
128 private static readonly int DefaultSpinCount = ((Environment.ProcessorCount != 1) ? 500 : 0);
129
130 private static long s_mostRecentLockID;
131
133
135
136 private readonly long _lockID;
137
138 private volatile int _state;
139
140 private int _writerID = -1;
141
142 private int _writerSeqNum = 1;
143
144 private ushort _writerLevel;
145
147 {
148 get
149 {
151 if (current != null)
152 {
153 return current._readerLevel > 0;
154 }
155 return false;
156 }
157 }
158
160
162
167
168 public bool AnyWritersSince(int seqNum)
169 {
171 {
172 seqNum++;
173 }
174 return (uint)_writerSeqNum > (uint)seqNum;
175 }
176
177 [UnsupportedOSPlatform("browser")]
179 {
180 if (millisecondsTimeout < -1)
181 {
182 throw GetInvalidTimeoutException("millisecondsTimeout");
183 }
185 if (Interlocked.CompareExchange(ref _state, 1, 0) != 0)
186 {
187 if (orCreateCurrent._readerLevel > 0)
188 {
189 if (orCreateCurrent._readerLevel == ushort.MaxValue)
190 {
192 }
193 orCreateCurrent._readerLevel++;
194 return;
195 }
197 {
199 return;
200 }
201 int num = 0;
202 int num2 = _state;
203 do
204 {
205 int num3 = num2;
206 if (num3 < 1023 || (((uint)num3 & 0x400u) != 0 && (num3 & 0x1000) == 0 && (num3 & 0x3FF) + ((num3 & 0x7FE000) >> 13) <= 1021))
207 {
209 if (num2 == num3)
210 {
211 break;
212 }
213 continue;
214 }
215 if ((num3 & 0x3FF) == 1023 || (num3 & 0x7FE000) == 8380416 || (num3 & 0xC00) == 1024)
216 {
217 int millisecondsTimeout2 = 100;
218 if ((num3 & 0x3FF) == 1023 || (num3 & 0x7FE000) == 8380416)
219 {
221 }
223 num = 0;
224 num2 = _state;
225 continue;
226 }
227 num++;
228 if ((num3 & 0xC00) == 3072)
229 {
230 if (num > DefaultSpinCount)
231 {
232 Thread.Sleep(1);
233 num = 0;
234 }
235 num2 = _state;
236 continue;
237 }
238 if (num <= DefaultSpinCount)
239 {
240 num2 = _state;
241 continue;
242 }
244 if (num2 != num3)
245 {
246 continue;
247 }
248 int num4 = -8192;
250 bool flag = false;
251 try
252 {
255 if (flag)
256 {
257 num4++;
258 }
259 }
260 finally
261 {
263 if (!flag && ((uint)num3 & 0x400u) != 0 && (num3 & 0x7FE000) == 8192)
264 {
265 if (manualResetEventSlim == null)
266 {
268 }
270 manualResetEventSlim.Reset();
271 Interlocked.Add(ref _state, -1023);
272 orCreateCurrent._readerLevel++;
274 }
275 }
276 if (!flag)
277 {
278 throw GetTimeoutException();
279 }
280 if ((num3 & 0x7FE000) == 8192)
281 {
282 manualResetEventSlim.Reset();
283 Interlocked.Add(ref _state, -1024);
284 }
285 break;
286 }
287 while (YieldProcessor());
288 }
289 orCreateCurrent._readerLevel++;
290 }
291
292 [UnsupportedOSPlatform("browser")]
297
299 {
300 if (millisecondsTimeout < -1)
301 {
302 throw GetInvalidTimeoutException("millisecondsTimeout");
303 }
305 if (Interlocked.CompareExchange(ref _state, 4096, 0) != 0)
306 {
308 {
309 if (_writerLevel == ushort.MaxValue)
310 {
312 }
313 _writerLevel++;
314 return;
315 }
316 int num = 0;
317 int num2 = _state;
318 do
319 {
320 int num3 = num2;
321 if (num3 == 0 || num3 == 3072)
322 {
324 if (num2 == num3)
325 {
326 break;
327 }
328 continue;
329 }
330 if ((num3 & -8388608) == -8388608)
331 {
332 Thread.Sleep(1000);
333 num = 0;
334 num2 = _state;
335 continue;
336 }
337 num++;
338 if ((num3 & 0xC00) == 3072)
339 {
340 if (num > DefaultSpinCount)
341 {
342 Thread.Sleep(1);
343 num = 0;
344 }
345 num2 = _state;
346 continue;
347 }
348 if (num <= DefaultSpinCount)
349 {
350 num2 = _state;
351 continue;
352 }
354 if (num2 != num3)
355 {
356 continue;
357 }
358 int num4 = -8388608;
360 bool flag = false;
361 try
362 {
364 flag = autoResetEvent.WaitOne(millisecondsTimeout);
365 if (flag)
366 {
367 num4 += 2048;
368 }
369 }
370 finally
371 {
373 if (!flag && ((uint)num3 & 0x800u) != 0 && (num3 & -8388608) == 8388608)
374 {
375 if (autoResetEvent == null)
376 {
378 }
379 while (true)
380 {
381 num3 = _state;
382 if (((uint)num3 & 0x800u) != 0 && (num3 & -8388608) == 0)
383 {
384 if (autoResetEvent.WaitOne(10))
385 {
386 num4 = 2048;
389 _writerLevel = 1;
391 break;
392 }
393 continue;
394 }
395 break;
396 }
397 }
398 }
399 if (flag)
400 {
401 break;
402 }
403 throw GetTimeoutException();
404 }
405 while (YieldProcessor());
406 }
408 _writerLevel = 1;
410 }
411
416
417 public void ReleaseReaderLock()
418 {
420 {
422 return;
423 }
425 if (current == null)
426 {
427 throw GetNotOwnerException();
428 }
429 current._readerLevel--;
430 if (current._readerLevel > 0)
431 {
432 return;
433 }
436 int num = _state;
437 bool flag;
438 bool flag2;
439 int num2;
440 do
441 {
442 flag = false;
443 flag2 = false;
444 num2 = num;
445 int num3 = -1;
446 if ((num2 & 0x7FF) == 1)
447 {
448 flag = true;
449 if (((uint)num2 & 0xFF800000u) != 0)
450 {
452 if (autoResetEvent == null)
453 {
454 Thread.Sleep(100);
455 num = _state;
456 num2 = 0;
457 continue;
458 }
459 num3 += 2048;
460 }
461 else if (((uint)num2 & 0x7FE000u) != 0)
462 {
464 if (manualResetEventSlim == null)
465 {
466 Thread.Sleep(100);
467 num = _state;
468 num2 = 0;
469 continue;
470 }
471 num3 += 1024;
472 }
473 else if (num2 == 1 && (_readerEvent != null || _writerEvent != null))
474 {
475 flag2 = true;
476 num3 += 3072;
477 }
478 }
480 }
481 while (num != num2);
482 if (flag)
483 {
484 if (((uint)num2 & 0xFF800000u) != 0)
485 {
486 autoResetEvent.Set();
487 }
488 else if (((uint)num2 & 0x7FE000u) != 0)
489 {
491 }
492 else if (flag2)
493 {
495 }
496 }
497 }
498
499 public void ReleaseWriterLock()
500 {
502 {
503 throw GetNotOwnerException();
504 }
505 _writerLevel--;
506 if (_writerLevel > 0)
507 {
508 return;
509 }
510 _writerID = -1;
513 int num = _state;
514 bool flag;
515 int num2;
516 do
517 {
518 flag = false;
519 num2 = num;
520 int num3 = -4096;
521 if (((uint)num2 & 0x7FE000u) != 0)
522 {
524 if (manualResetEventSlim == null)
525 {
526 Thread.Sleep(100);
527 num = _state;
528 num2 = 0;
529 continue;
530 }
531 num3 += 1024;
532 }
533 else if (((uint)num2 & 0xFF800000u) != 0)
534 {
536 if (autoResetEvent == null)
537 {
538 Thread.Sleep(100);
539 num = _state;
540 num2 = 0;
541 continue;
542 }
543 num3 += 2048;
544 }
545 else if (num2 == 4096 && (_readerEvent != null || _writerEvent != null))
546 {
547 flag = true;
548 num3 += 3072;
549 }
551 }
552 while (num != num2);
553 if (((uint)num2 & 0x7FE000u) != 0)
554 {
556 }
557 else if (((uint)num2 & 0xFF800000u) != 0)
558 {
559 autoResetEvent.Set();
560 }
561 else if (flag)
562 {
564 }
565 }
566
567 [UnsupportedOSPlatform("browser")]
569 {
570 if (millisecondsTimeout < -1)
571 {
572 throw GetInvalidTimeoutException("millisecondsTimeout");
573 }
576 if (_writerID == num)
577 {
581 return lockCookie;
582 }
584 if (current == null)
585 {
587 }
588 else
589 {
592 int num2 = Interlocked.CompareExchange(ref _state, 4096, 1);
593 if (num2 == 1)
594 {
596 _writerID = num;
597 _writerLevel = 1;
599 return lockCookie;
600 }
603 }
604 bool flag = false;
605 try
606 {
608 flag = true;
609 return lockCookie;
610 }
611 finally
612 {
613 if (!flag)
614 {
615 LockCookieFlags flags = lockCookie._flags;
617 RecoverLock(ref lockCookie, flags & LockCookieFlags.OwnedReader);
618 }
619 }
620 }
621
622 [UnsupportedOSPlatform("browser")]
627
629 {
632 {
633 throw GetNotOwnerException();
634 }
635 LockCookieFlags flags = lockCookie._flags;
636 ushort writerLevel = lockCookie._writerLevel;
637 if (((uint)flags & 0xFFF89FFFu) != 0 || lockCookie._threadID != currentThreadID || ((flags & (LockCookieFlags.OwnedNone | LockCookieFlags.OwnedWriter)) != 0 && _writerLevel <= writerLevel))
638 {
640 }
641 if ((flags & LockCookieFlags.OwnedReader) != 0)
642 {
644 _writerID = -1;
645 _writerLevel = 0;
647 int num = _state;
648 int num2;
649 do
650 {
651 num2 = num;
652 int num3 = -4095;
653 if (((uint)num2 & 0x7FE000u) != 0)
654 {
656 if (manualResetEventSlim == null)
657 {
658 Thread.Sleep(100);
659 num = _state;
660 num2 = 0;
661 continue;
662 }
663 num3 += 1024;
664 }
666 }
667 while (num != num2);
668 if (((uint)num2 & 0x7FE000u) != 0)
669 {
671 }
673 }
674 else if ((flags & (LockCookieFlags.OwnedNone | LockCookieFlags.OwnedWriter)) != 0)
675 {
676 if (writerLevel > 0)
677 {
679 }
680 else
681 {
682 if (_writerLevel != 1)
683 {
684 _writerLevel = 1;
685 }
687 }
688 }
690 }
691
693 {
694 LockCookie result = default(LockCookie);
695 int num = (result._threadID = GetCurrentThreadID());
696 if (_writerID == num)
697 {
700 _writerLevel = 1;
702 return result;
703 }
705 if (current == null)
706 {
708 return result;
709 }
714 return result;
715 }
716
717 [UnsupportedOSPlatform("browser")]
719 {
721 if (lockCookie._threadID != currentThreadID)
722 {
724 }
726 {
728 }
729 LockCookieFlags flags = lockCookie._flags;
730 if (((uint)flags & 0xFFF89FFFu) != 0)
731 {
733 }
734 if ((flags & LockCookieFlags.OwnedNone) == 0)
735 {
736 if ((flags & LockCookieFlags.OwnedWriter) != 0)
737 {
738 if (Interlocked.CompareExchange(ref _state, 4096, 0) == 0)
739 {
741 _writerLevel = lockCookie._writerLevel;
743 goto IL_00e5;
744 }
745 }
746 else if ((flags & LockCookieFlags.OwnedReader) != 0)
747 {
749 int state = _state;
750 if (state < 1023 && Interlocked.CompareExchange(ref _state, state + 1, state) == state)
751 {
753 goto IL_00e5;
754 }
755 }
756 RecoverLock(ref lockCookie, flags);
757 }
758 goto IL_00e5;
759 IL_00e5:
761 }
762
763 [UnsupportedOSPlatform("browser")]
765 {
766 if ((flags & LockCookieFlags.OwnedWriter) != 0)
767 {
769 _writerLevel = lockCookie._writerLevel;
770 }
771 else if ((flags & LockCookieFlags.OwnedReader) != 0)
772 {
775 current._readerLevel = lockCookie._readerLevel;
776 }
777 }
778
779 private static int GetCurrentThreadID()
780 {
782 }
783
784 private static bool YieldProcessor()
785 {
786 Thread.SpinWait(1);
787 return true;
788 }
789
791 {
793 if (readerEvent != null)
794 {
795 return readerEvent;
796 }
797 readerEvent = new ManualResetEventSlim(initialState: false, 0);
799 if (manualResetEventSlim == null)
800 {
801 return readerEvent;
802 }
803 readerEvent.Dispose();
805 }
806
808 {
810 if (writerEvent != null)
811 {
812 return writerEvent;
813 }
814 writerEvent = new AutoResetEvent(initialState: false);
816 if (autoResetEvent == null)
817 {
818 return writerEvent;
819 }
820 writerEvent.Dispose();
821 return autoResetEvent;
822 }
823
825 {
826 try
827 {
828 return GetOrCreateReaderEvent();
829 }
830 catch
831 {
832 return null;
833 }
834 }
835
837 {
838 try
839 {
840 return GetOrCreateWriterEvent();
841 }
842 catch
843 {
844 return null;
845 }
846 }
847
848 private void ReleaseEvents()
849 {
851 _writerEvent = null;
853 _readerEvent = null;
854 Interlocked.Add(ref _state, -3072);
855 writerEvent?.Dispose();
856 readerEvent?.Dispose();
857 }
858
863
865 {
866 long num = (long)timeout.TotalMilliseconds;
867 if (num < -1 || num > int.MaxValue)
868 {
869 throw GetInvalidTimeoutException("timeout");
870 }
871 return (int)num;
872 }
873
878
883
888}
static int CurrentManagedThreadId
static string ReaderWriterLock_NotOwner
Definition SR.cs:52
static string Overflow_UInt16
Definition SR.cs:1786
static string ReaderWriterLock_Timeout
Definition SR.cs:48
static string ReaderWriterLock_InvalidLockCookie
Definition SR.cs:56
static string ArgumentOutOfRange_TimeoutMilliseconds
Definition SR.cs:50
static string ReaderWriterLock_RestoreLockWithOwnedLocks
Definition SR.cs:58
Definition SR.cs:7
static int CompareExchange(ref int location1, int value, int comparand)
static int Add(ref int location1, int value)
static int Increment(ref int location)
ReaderWriterLockApplicationException(SerializationInfo info, StreamingContext context)
static ThreadLocalLockEntry GetOrCreateCurrentSlow(long lockID, ThreadLocalLockEntry headEntry)
static ThreadLocalLockEntry GetOrCreateCurrent(long lockID)
static ThreadLocalLockEntry GetCurrent(long lockID)
static ApplicationException GetNotOwnerException()
static ApplicationException GetTimeoutException()
static int ToTimeoutMilliseconds(TimeSpan timeout)
void AcquireReaderLock(TimeSpan timeout)
void RestoreLock(ref LockCookie lockCookie)
LockCookie UpgradeToWriterLock(TimeSpan timeout)
void RecoverLock(ref LockCookie lockCookie, LockCookieFlags flags)
void AcquireWriterLock(int millisecondsTimeout)
void AcquireWriterLock(TimeSpan timeout)
static ApplicationException GetInvalidLockCookieException()
ManualResetEventSlim TryGetOrCreateReaderEvent()
void DowngradeFromWriterLock(ref LockCookie lockCookie)
static ArgumentOutOfRangeException GetInvalidTimeoutException(string parameterName)
ManualResetEventSlim GetOrCreateReaderEvent()
LockCookie UpgradeToWriterLock(int millisecondsTimeout)
void AcquireReaderLock(int millisecondsTimeout)
static void Sleep(int millisecondsTimeout)
Definition Thread.cs:658
static void SpinWait(int iterations)
Definition Thread.cs:404