8
8
#define BUF_SIZE 4096
9
9
10
10
typedef struct {
11
- uint32_t rpos , wpos , apos ;
11
+ uint32_t rpos , wpos , apos , fpos ;
12
12
char_u data [BUF_SIZE ];
13
13
} input_buffer_T ;
14
14
15
+ static uv_handle_type stdin_type ;
15
16
static int pending_signal = 0 ;
16
17
static uv_thread_t thread ;
17
18
static uv_mutex_t mutex ;
@@ -26,7 +27,9 @@ static void loop_running(uv_idle_t *, int);
26
27
static void stop_loop (uv_async_t * , int );
27
28
static void alloc_cb (uv_handle_t * , size_t , uv_buf_t * );
28
29
static void read_cb (uv_stream_t * , ssize_t , const uv_buf_t * );
30
+ static void fread_cb (uv_fs_t * );
29
31
static void signal_cb (uv_signal_t * , int signum );
32
+ static void relocate (void );
30
33
static void io_lock (void );
31
34
static void io_unlock (void );
32
35
static void io_timedwait (uint64_t ms , bool * condition );
@@ -160,9 +163,11 @@ static void event_loop(void *arg)
160
163
uv_loop_t * loop ;
161
164
uv_idle_t idler ;
162
165
uv_signal_t sint , shup , squit , sabrt , sterm , swinch ;
163
- uv_pipe_t stdin_stream ;
166
+ uv_stream_t * stdin_stream = NULL ;
167
+ uv_fs_t * read_req = NULL ;
164
168
165
- in_buffer .wpos = in_buffer .rpos = in_buffer .apos = 0 ;
169
+
170
+ in_buffer .wpos = in_buffer .rpos = in_buffer .apos = in_buffer .fpos = 0 ;
166
171
#ifdef DEBUG
167
172
memset (& in_buffer .data , 0 , BUF_SIZE );
168
173
#endif
@@ -173,17 +178,30 @@ static void event_loop(void *arg)
173
178
pthread_sigmask (SIG_SETMASK , & set , NULL );
174
179
175
180
loop = uv_loop_new ();
181
+
182
+ /* Setup stdin_stream */
183
+ if ((stdin_type = uv_guess_handle (read_cmd_fd )) == UV_FILE ) {
184
+ read_req = (uv_fs_t * )malloc (sizeof (uv_fs_t ));
185
+ in_buffer .apos = BUF_SIZE ;
186
+ uv_fs_read (loop , read_req , read_cmd_fd , in_buffer .data , BUF_SIZE ,
187
+ in_buffer .fpos , fread_cb );
188
+ } else if (stdin_type == UV_FILE ) {
189
+ stdin_stream = (uv_stream_t * )malloc (sizeof (uv_tty_t ));
190
+ uv_tty_init (loop , (uv_tty_t * )stdin_stream , read_cmd_fd , 1 );
191
+ } else {
192
+ /* FIXME setting fd to non-blocking is only needed on unix */
193
+ // fcntl(read_cmd_fd, F_SETFL, fcntl(read_cmd_fd, F_GETFL, 0) | O_NONBLOCK);
194
+ stdin_stream = (uv_stream_t * )malloc (sizeof (uv_pipe_t ));
195
+ uv_pipe_init (loop , (uv_pipe_t * )stdin_stream , 0 );
196
+ uv_pipe_open ((uv_pipe_t * )stdin_stream , read_cmd_fd );
197
+ }
198
+
176
199
/* Idler for signaling the main thread when the loop is running */
177
200
uv_idle_init (loop , & idler );
178
- idler .data = & stdin_stream ;
201
+ idler .data = stdin_stream ;
179
202
uv_idle_start (& idler , loop_running );
180
203
/* Async watcher used by the main thread to stop the loop */
181
204
uv_async_init (loop , & stop_loop_async , stop_loop );
182
- /* stdin */
183
- /* FIXME setting fd to non-blocking is only needed on unix */
184
- fcntl (read_cmd_fd , F_SETFL , fcntl (read_cmd_fd , F_GETFL , 0 ) | O_NONBLOCK );
185
- uv_pipe_init (loop , & stdin_stream , 0 );
186
- uv_pipe_open (& stdin_stream , read_cmd_fd );
187
205
/* signals */
188
206
uv_signal_init (loop , & sint );
189
207
uv_signal_start (& sint , signal_cb , SIGINT );
@@ -199,6 +217,15 @@ static void event_loop(void *arg)
199
217
uv_signal_start (& swinch , signal_cb , SIGWINCH );
200
218
/* start processing events */
201
219
uv_run (loop , UV_RUN_DEFAULT );
220
+
221
+ if (stdin_stream != NULL )
222
+ free (stdin_stream );
223
+
224
+ if (read_req != NULL ) {
225
+ uv_cancel ((uv_req_t * )read_req );
226
+ free (read_req );
227
+ }
228
+
202
229
/* free the event loop */
203
230
uv_loop_delete (loop );
204
231
}
@@ -208,7 +235,8 @@ static void loop_running(uv_idle_t *handle, int status)
208
235
{
209
236
uv_idle_stop (handle );
210
237
io_lock ();
211
- uv_read_start ((uv_stream_t * )handle -> data , alloc_cb , read_cb );
238
+ if (stdin_type != UV_FILE )
239
+ uv_read_start ((uv_stream_t * )handle -> data , alloc_cb , read_cb );
212
240
io_notify (& running );
213
241
io_unlock ();
214
242
}
@@ -240,8 +268,6 @@ static void alloc_cb(uv_handle_t *handle, size_t ssize, uv_buf_t *rv)
240
268
*/
241
269
static void read_cb (uv_stream_t * stream , ssize_t cnt , const uv_buf_t * buf )
242
270
{
243
- uint32_t move_count ;
244
-
245
271
io_lock ();
246
272
247
273
if (cnt < 0 ) {
@@ -255,24 +281,10 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf)
255
281
io_notify (& activity );
256
282
}
257
283
} else if (cnt == UV_ENOBUFS ) {
258
- if (in_buffer .apos > in_buffer .wpos ) {
259
- /* Restore `apos` to `wpos` */
260
- in_buffer .apos = in_buffer .wpos ;
261
- } else {
262
- if (in_buffer .rpos == 0 ) {
263
- /* Pause until the main thread consumes some data. */
264
- io_notify (& activity );
265
- io_wait (& input_consumed );
266
- }
267
- /* Move data to the 'left' as much as possible. */
268
- move_count = in_buffer .apos - in_buffer .rpos ;
269
- memmove (in_buffer .data , in_buffer .data + in_buffer .rpos , move_count );
270
- in_buffer .apos -= in_buffer .rpos ;
271
- in_buffer .wpos -= in_buffer .rpos ;
272
- in_buffer .rpos = 0 ;
273
- }
284
+ io_notify (& activity );
285
+ relocate ();
274
286
} else {
275
- fprintf (stderr , "Unexpected error %ld \n" , cnt );
287
+ fprintf (stderr , "Unexpected error %s \n" , uv_strerror ( cnt ) );
276
288
}
277
289
io_unlock ();
278
290
return ;
@@ -289,6 +301,43 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf)
289
301
io_unlock ();
290
302
}
291
303
304
+ static void fread_cb (uv_fs_t * req )
305
+ {
306
+ uint32_t available ;
307
+
308
+ uv_fs_req_cleanup (req );
309
+ io_lock ();
310
+
311
+ if (req -> result <= 0 ) {
312
+ if (req -> result == 0 ) {
313
+ /* EOF, stop the event loop and signal the main thread. This will cause
314
+ * vim to exit */
315
+ if (!eof ) {
316
+ /* Dont close the loop if it was already closed in `io_stop` */
317
+ eof = true;
318
+ uv_stop (req -> loop );
319
+ io_notify (& activity );
320
+ }
321
+ } else {
322
+ fprintf (stderr , "Unexpected error %s\n" , uv_strerror (req -> result ));
323
+ }
324
+ io_unlock ();
325
+ return ;
326
+ }
327
+
328
+ in_buffer .wpos += req -> result ;
329
+ in_buffer .fpos += req -> result ;
330
+ io_notify (& activity );
331
+ relocate ();
332
+ io_unlock ();
333
+
334
+ available = BUF_SIZE - in_buffer .apos ;
335
+ /* Read more */
336
+ uv_fs_read (req -> loop , req , read_cmd_fd , in_buffer .data + in_buffer .apos ,
337
+ available , in_buffer .fpos , fread_cb );
338
+ in_buffer .apos += available ;
339
+ }
340
+
292
341
static void signal_cb (uv_signal_t * handle , int signum )
293
342
{
294
343
io_lock ();
@@ -298,6 +347,29 @@ static void signal_cb(uv_signal_t *handle, int signum)
298
347
io_unlock ();
299
348
}
300
349
350
+ static void relocate ()
351
+ {
352
+ uint32_t move_count ;
353
+
354
+ if (in_buffer .apos > in_buffer .wpos ) {
355
+ /* Restore `apos` to `wpos` */
356
+ in_buffer .apos = in_buffer .wpos ;
357
+ return ;
358
+ }
359
+
360
+ if (in_buffer .rpos == 0 ) {
361
+ /* Pause until the main thread consumes some data. */
362
+ io_wait (& input_consumed );
363
+ }
364
+
365
+ /* Move data to the 'left' as much as possible. */
366
+ move_count = in_buffer .apos - in_buffer .rpos ;
367
+ memmove (in_buffer .data , in_buffer .data + in_buffer .rpos , move_count );
368
+ in_buffer .apos -= in_buffer .rpos ;
369
+ in_buffer .wpos -= in_buffer .rpos ;
370
+ in_buffer .rpos = 0 ;
371
+ }
372
+
301
373
/* Helpers for dealing with io synchronization */
302
374
static void io_lock ()
303
375
{
0 commit comments