@@ -9,55 +9,25 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Console
99{
1010 internal class UnixConsoleOperations : IConsoleOperations
1111 {
12- private const int LongWaitForKeySleepTime = 300 ;
13-
14- private const int ShortWaitForKeyTimeout = 5000 ;
15-
16- private const int ShortWaitForKeySpinUntilSleepTime = 30 ;
17-
18- private static readonly ManualResetEventSlim s_waitHandle = new ( ) ;
19-
2012 private static readonly SemaphoreSlim s_readKeyHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
2113
2214 private static readonly SemaphoreSlim s_stdInHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
2315
24- private Func < CancellationToken , bool > WaitForKeyAvailable ;
25-
26- /// <summary>
27- /// Switch between long and short wait periods depending on if the user has recently (last 5
28- /// seconds) pressed a key to avoid preventing the CPU from entering low power mode.
29- /// </summary>
30- internal UnixConsoleOperations ( ) => WaitForKeyAvailable = LongWaitForKey ;
31-
3216 public ConsoleKeyInfo ReadKey ( bool intercept , CancellationToken cancellationToken )
3317 {
34- s_readKeyHandle . Wait ( cancellationToken ) ;
35-
36- // On Unix platforms System.Console.ReadKey has an internal lock on stdin. Because
37- // of this, if a ReadKey call is pending in one thread and in another thread
38- // Console.CursorLeft is called, both threads block until a key is pressed.
39- try
40- {
41- // The WaitForKeyAvailable delegate switches between a long delay between waits and
42- // a short timeout depending on how recently a key has been pressed. This allows us
43- // to let the CPU enter low power mode without compromising responsiveness.
44- while ( ! WaitForKeyAvailable ( cancellationToken ) ) { }
45- }
46- finally
47- {
48- s_readKeyHandle . Release ( ) ;
49- }
50-
5118 // A key has been pressed, so acquire a lock on our internal stdin handle. This is done
5219 // so any of our calls to cursor position API's do not release ReadKey.
5320 s_stdInHandle . Wait ( cancellationToken ) ;
21+ s_readKeyHandle . Wait ( cancellationToken ) ;
5422 try
5523 {
5624 return System . Console . ReadKey ( intercept ) ;
5725 }
5826 finally
5927 {
28+ s_readKeyHandle . Release ( ) ;
6029 s_stdInHandle . Release ( ) ;
30+ cancellationToken . ThrowIfCancellationRequested ( ) ;
6131 }
6232 }
6333
@@ -90,60 +60,5 @@ public int GetCursorTop(CancellationToken cancellationToken)
9060 s_stdInHandle . Release ( ) ;
9161 }
9262 }
93-
94- private bool LongWaitForKey ( CancellationToken cancellationToken )
95- {
96- // Wait for a key to be buffered (in other words, wait for Console.KeyAvailable to become
97- // true) with a long delay between checks.
98- while ( ! IsKeyAvailable ( cancellationToken ) )
99- {
100- s_waitHandle . Wait ( LongWaitForKeySleepTime , cancellationToken ) ;
101- }
102-
103- // As soon as a key is buffered, return true and switch the wait logic to be more
104- // responsive, but also more expensive.
105- WaitForKeyAvailable = ShortWaitForKey ;
106- return true ;
107- }
108-
109- private bool ShortWaitForKey ( CancellationToken cancellationToken )
110- {
111- // Check frequently for a new key to be buffered.
112- if ( SpinUntilKeyAvailable ( ShortWaitForKeyTimeout , cancellationToken ) )
113- {
114- cancellationToken . ThrowIfCancellationRequested ( ) ;
115- return true ;
116- }
117-
118- // If the user has not pressed a key before the end of the SpinUntil timeout then
119- // the user is idle and we can switch back to long delays between KeyAvailable checks.
120- cancellationToken . ThrowIfCancellationRequested ( ) ;
121- WaitForKeyAvailable = LongWaitForKey ;
122- return false ;
123- }
124-
125- private static bool SpinUntilKeyAvailable ( int millisecondsTimeout , CancellationToken cancellationToken )
126- {
127- return SpinWait . SpinUntil (
128- ( ) =>
129- {
130- s_waitHandle . Wait ( ShortWaitForKeySpinUntilSleepTime , cancellationToken ) ;
131- return IsKeyAvailable ( cancellationToken ) ;
132- } ,
133- millisecondsTimeout ) ;
134- }
135-
136- private static bool IsKeyAvailable ( CancellationToken cancellationToken )
137- {
138- s_stdInHandle . Wait ( cancellationToken ) ;
139- try
140- {
141- return System . Console . KeyAvailable ;
142- }
143- finally
144- {
145- s_stdInHandle . Release ( ) ;
146- }
147- }
14863 }
14964}
0 commit comments