Created
February 7, 2019 22:26
-
-
Save filipnavara/86cf7b27f0f20d86d6ebde9aebf158e1 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // Licensed to the .NET Foundation under one or more agreements. | |
| // The .NET Foundation licenses this file to you under the MIT license. | |
| // See the LICENSE file in the project root for more information. | |
| using System.Collections.Generic; | |
| namespace System.Threading | |
| { | |
| /// <summary> | |
| /// A LIFO semaphore. | |
| /// Waits on this semaphore are uninterruptible. | |
| /// </summary> | |
| internal sealed partial class LowLevelLifoSemaphore : IDisposable | |
| { | |
| private LowLevelLock _waiterStackLock; | |
| private WaiterListEntry _waiterStackHead; | |
| private LowLevelMonitor _fallbackMonitor; | |
| [ThreadStatic] | |
| private static WaiterListEntry t_waitEntry; | |
| private void Create(int maximumSignalCount) | |
| { | |
| _waiterStackLock = new LowLevelLock(); | |
| _fallbackMonitor = new LowLevelMonitor(); | |
| } | |
| public void Dispose() | |
| { | |
| } | |
| private bool WaitCore(int timeoutMs) | |
| { | |
| try | |
| { | |
| WaiterListEntry waitEntry = t_waitEntry ?? (t_waitEntry = new WaiterListEntry()); | |
| waitEntry._monitor.Acquire(); | |
| try | |
| { | |
| _waiterStackLock.Acquire(); | |
| waitEntry._next = _waiterStackHead; | |
| _waiterStackHead = waitEntry; | |
| _waiterStackLock.Release(); | |
| return waitEntry._monitor.Wait(timeoutMs); | |
| } | |
| finally | |
| { | |
| waitEntry._monitor.Release(); | |
| } | |
| } | |
| catch (OutOfMemoryException) | |
| { | |
| _fallbackMonitor.Acquire(); | |
| try | |
| { | |
| return _fallbackMonitor.Wait(timeoutMs); | |
| } | |
| finally | |
| { | |
| _fallbackMonitor.Release(); | |
| } | |
| } | |
| } | |
| private void ReleaseCore(int count) | |
| { | |
| while (count > 0) | |
| { | |
| _waiterStackLock.Acquire(); | |
| WaiterListEntry waitEntry = _waiterStackHead; | |
| _waiterStackHead = waitEntry?._next; | |
| _waiterStackLock.Release(); | |
| if (waitEntry != null) | |
| { | |
| waitEntry._monitor.Acquire(); | |
| waitEntry._monitor.Signal_Release(); | |
| count--; | |
| } | |
| else | |
| { | |
| break; | |
| } | |
| } | |
| while (count-- > 0) | |
| { | |
| _fallbackMonitor.Acquire(); | |
| _fallbackMonitor.Signal_Release(); | |
| } | |
| } | |
| class WaiterListEntry | |
| { | |
| public LowLevelMonitor _monitor; | |
| public WaiterListEntry _next; | |
| public WaiterListEntry() | |
| { | |
| this._monitor = new LowLevelMonitor(); | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment