@@ -9,55 +9,25 @@ namespace Microsoft.PowerShell.EditorServices.Services.PowerShell.Console
9
9
{
10
10
internal class UnixConsoleOperations : IConsoleOperations
11
11
{
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
-
20
12
private static readonly SemaphoreSlim s_readKeyHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
21
13
22
14
private static readonly SemaphoreSlim s_stdInHandle = AsyncUtils . CreateSimpleLockingSemaphore ( ) ;
23
15
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
-
32
16
public ConsoleKeyInfo ReadKey ( bool intercept , CancellationToken cancellationToken )
33
17
{
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
-
51
18
// A key has been pressed, so acquire a lock on our internal stdin handle. This is done
52
19
// so any of our calls to cursor position API's do not release ReadKey.
53
20
s_stdInHandle . Wait ( cancellationToken ) ;
21
+ s_readKeyHandle . Wait ( cancellationToken ) ;
54
22
try
55
23
{
56
24
return System . Console . ReadKey ( intercept ) ;
57
25
}
58
26
finally
59
27
{
28
+ s_readKeyHandle . Release ( ) ;
60
29
s_stdInHandle . Release ( ) ;
30
+ cancellationToken . ThrowIfCancellationRequested ( ) ;
61
31
}
62
32
}
63
33
@@ -90,60 +60,5 @@ public int GetCursorTop(CancellationToken cancellationToken)
90
60
s_stdInHandle . Release ( ) ;
91
61
}
92
62
}
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
- }
148
63
}
149
64
}
0 commit comments