Reimplement input functions on top of libuv

The functions `mch_inchar`, `mch_breakcheck`, `mch_char_avail` were
reimplemented on top of libuv. Here's how it works:

- When Neovim needs to wait for characters, it will transfer control to libuv
  event loop.
- When the libuv event loop gets user input, it will transfer control back to
  Neovim
- Neovim uses the `input_read` function to get the actual data read by libuv.

With this scheme its possible to keep Neovim single-threaded while enjoying the
benefits provided by libuv.

This commit leaves SIGWINCH broken for now
This commit is contained in:
Thiago de Arruda
2014-03-26 16:35:24 -03:00
parent f8432ef127
commit 452804638d
7 changed files with 392 additions and 154 deletions

View File

@@ -31,7 +31,6 @@
#include "vim.h"
#include "os_unix.h"
#include "os/time.h"
#include "buffer.h"
#include "charset.h"
#include "eval.h"
@@ -51,6 +50,8 @@
#include "ui.h"
#include "os/os.h"
#include "os/time.h"
#include "os/event.h"
#include "os/input.h"
#include "os_unixx.h" /* unix includes for os_unix.c only */
@@ -108,7 +109,6 @@ typedef int waitstatus;
#endif
static pid_t wait4pid(pid_t, waitstatus *);
static int WaitForChar(long);
static int RealWaitForChar(int, long, int *);
@@ -248,98 +248,12 @@ void mch_write(char_u *s, int len)
RealWaitForChar(read_cmd_fd, p_wd, NULL);
}
/*
* mch_inchar(): low level input function.
* Get a characters from the keyboard.
* Return the number of characters that are available.
* If wtime == 0 do not wait for characters.
* If wtime == n wait a short time for characters.
* If wtime == -1 wait forever for characters.
*/
int mch_inchar(
char_u *buf,
int maxlen,
long wtime, /* don't use "time", MIPS cannot handle it */
int tb_change_cnt
)
{
int len;
/* Check if window changed size while we were busy, perhaps the ":set
* columns=99" command was used. */
while (do_resize)
handle_resize();
if (wtime >= 0) {
while (WaitForChar(wtime) == 0) { /* no character available */
if (!do_resize) /* return if not interrupted by resize */
return 0;
handle_resize();
}
} else { /* wtime == -1 */
/*
* If there is no character available within 'updatetime' seconds
* flush all the swap files to disk.
* Also done when interrupted by SIGWINCH.
*/
if (WaitForChar(p_ut) == 0) {
if (trigger_cursorhold() && maxlen >= 3
&& !typebuf_changed(tb_change_cnt)) {
buf[0] = K_SPECIAL;
buf[1] = KS_EXTRA;
buf[2] = (int)KE_CURSORHOLD;
return 3;
}
before_blocking();
}
}
for (;; ) { /* repeat until we got a character */
while (do_resize) /* window changed size */
handle_resize();
/*
* We want to be interrupted by the winch signal
* or by an event on the monitored file descriptors.
*/
if (WaitForChar(-1L) == 0) {
if (do_resize) /* interrupted by SIGWINCH signal */
handle_resize();
return 0;
}
/* If input was put directly in typeahead buffer bail out here. */
if (typebuf_changed(tb_change_cnt))
return 0;
/*
* For some terminals we only get one character at a time.
* We want the get all available characters, so we could keep on
* trying until none is available
* For some other terminals this is quite slow, that's why we don't do
* it.
*/
len = read_from_input_buf(buf, (long)maxlen);
if (len > 0) {
return len;
}
}
}
static void handle_resize()
{
do_resize = FALSE;
shell_resized();
}
/*
* return non-zero if a character is available
*/
int mch_char_avail()
{
return WaitForChar(0L);
}
#if defined(HAVE_SIGALTSTACK) || defined(HAVE_SIGSTACK)
/*
@@ -682,6 +596,8 @@ void mch_init()
#ifdef MACOS_CONVERT
mac_conv_init();
#endif
event_init();
}
static void set_signals()
@@ -2460,43 +2376,6 @@ error:
return retval;
}
/*
* Check for CTRL-C typed by reading all available characters.
* In cooked mode we should get SIGINT, no need to check.
*/
void mch_breakcheck()
{
if (curr_tmode == TMODE_RAW && RealWaitForChar(read_cmd_fd, 0L, NULL))
fill_input_buf(FALSE);
}
/*
* Wait "msec" msec until a character is available from the keyboard or from
* inbuf[]. msec == -1 will block forever.
* When a GUI is being used, this will never get called -- webb
*/
static int WaitForChar(msec)
long msec;
{
int avail;
if (input_available()) /* something in inbuf[] */
return 1;
/* May need to query the mouse position. */
if (WantQueryMouse) {
WantQueryMouse = FALSE;
mch_write((char_u *)IF_EB("\033[1'|", ESC_STR "[1'|"), 5);
}
/*
* For FEAT_MOUSE_GPM and FEAT_XCLIPBOARD we loop here to process mouse
* events. This is a bit complicated, because they might both be defined.
*/
avail = RealWaitForChar(read_cmd_fd, msec, NULL);
return avail;
}
/*
* Wait "msec" msec until a character is available from file descriptor "fd".
* "msec" == 0 will check for characters once.