66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
|
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
+
+
+
+
+
-
-
+
+
+
+
+
+
-
+
|
* Locks are never held when calling the ReadConsole/WriteConsole API's
* since they may block.
*/
static int gInitialized = 0;
/*
* INPUT_BUFFER_SIZE is size of buffer passed to ReadConsole in bytes.
* Note that ReadConsole will only allow reading of line lengths up to the
* max of 256 and buffer size passed to it. So dropping this below 512
* means user can type at most 256 chars.
*/
* Permit CONSOLE_BUFFER_SIZE to be defined on build command for stress test.
*
#ifndef INPUT_BUFFER_SIZE
#define INPUT_BUFFER_SIZE 8192 /* In bytes, so 4096 chars */
#endif
/*
* CONSOLE_BUFFER_SIZE is size of storage used in ring buffers.
* In theory, at least sizeof(WCHAR) but note the Tcl channel bug
* https://core.tcl-lang.org/tcl/tktview/b3977d199b08e3979a8da970553d5209b3042e9c
* will cause failures in test suite if close to max input line in the suite.
*/
#ifndef CONSOLE_BUFFER_SIZE
#define CONSOLE_BUFFER_SIZE 8000 /* In bytes */
#define CONSOLE_BUFFER_SIZE 8192 /* In bytes */
#endif
/*
* Ring buffer for storing data. Actual data is from bufPtr[start]:bufPtr[size-1]
* and bufPtr[0]:bufPtr[length - (size-start)].
*/
typedef struct RingBuffer {
|
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
|
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
|
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
|
*errorCode = EWOULDBLOCK;
numRead = -1;
break;
}
/*
* Blocking read. Just get data from directly from console. There
* is a small complication in that we can only read even number
* of bytes (wide-character API) and the destination buffer should be
* WCHAR aligned. If either condition is not met, we defer to the
* reader thread which handles these case rather than dealing with
* is a small complication in that
* 1. The destination buffer should be WCHAR aligned.
* 2. We can only read even number of bytes (wide-character API).
* 3. Caller has large enough buffer (else length of line user can
* enter will be limited)
* If any condition is not met, we defer to the
* reader thread which handles these cases rather than dealing with
* them here (which is a little trickier than it might sound.)
*
* TODO - not clear this block is a useful optimization. bufSize by
* default is 4K which is < INPUT_BUFFER_SIZE and will rarely be
* increased on stdin.
*/
if ((1 & (size_t)bufPtr) == 0 /* aligned buffer */
&& (1 & bufSize) == 0 /* Even number of bytes */
&& bufSize > 1 /* Not single byte read */
&& bufSize > INPUT_BUFFER_SIZE) {
) {
DWORD lastError;
Tcl_Size numChars;
ReleaseSRWLockExclusive(&handleInfoPtr->lock);
lastError = ReadConsoleChars(chanInfoPtr->handle,
(WCHAR *)bufPtr,
bufSize / sizeof(WCHAR),
&numChars);
|
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
|
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
|
-
-
-
-
-
-
+
|
{
ConsoleHandleInfo *handleInfoPtr = (ConsoleHandleInfo *) arg;
ConsoleHandleInfo **iterator;
Tcl_Size inputLen = 0;
Tcl_Size inputOffset = 0;
Tcl_Size lastReadSize = 0;
DWORD sleepTime;
/*
* ReadConsole will limit input to the greater of 256 characters
* and the size of the input buffer. 8.6 used 8192 (4096 chars)
* and so do we.
*/
char inputChars[8192];
char inputChars[INPUT_BUFFER_SIZE];
/*
* Keep looping until one of the following happens.
* - there are no more channels listening on the console
* - the console handle has been closed
*/
|