Code

IO API: use select(2) to check if pipe is readable when updating a view
authorJonas Fonseca <fonseca@diku.dk>
Sun, 9 Nov 2008 20:04:45 +0000 (21:04 +0100)
committerJonas Fonseca <fonseca@diku.dk>
Tue, 13 Jan 2009 21:55:20 +0000 (22:55 +0100)
NEWS
tig.c

diff --git a/NEWS b/NEWS
index 0463230378bda402844441b449eab14760703825..31ef9d529126a042f47195c7e881d4321445ff38 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -18,6 +18,7 @@ Improvements:
  - Add bash completion for blame.
  - Tree view: edit files of the current branch.
  - Run requests: new identifiers %(directory), %(file), and %(ref)
+ - Improve responsiveness and view loading speed by using select(2).
 
 Bug fixes:
 
diff --git a/tig.c b/tig.c
index 36c32cd99962ebb92a4075c8503014ec15144190..544fd8544331ddf143c2659e9f747d89171c5da9 100644 (file)
--- a/tig.c
+++ b/tig.c
@@ -34,6 +34,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <sys/select.h>
 #include <unistd.h>
 #include <time.h>
 #include <fcntl.h>
@@ -509,6 +510,18 @@ io_strerror(struct io *io)
        return strerror(io->error);
 }
 
+static bool
+io_can_read(struct io *io)
+{
+       struct timeval tv = { 0, 500 };
+       fd_set fds;
+
+       FD_ZERO(&fds);
+       FD_SET(io->pipe, &fds);
+
+       return select(io->pipe + 1, &fds, NULL, NULL, &tv) > 0;
+}
+
 static ssize_t
 io_read(struct io *io, void *buf, size_t bufsize)
 {
@@ -2666,24 +2679,20 @@ update_view(struct view *view)
 {
        char out_buffer[BUFSIZ * 2];
        char *line;
-       /* The number of lines to read. If too low it will cause too much
-        * redrawing (and possible flickering), if too high responsiveness
-        * will suffer. */
-       unsigned long lines = view->height;
        int redraw_from = -1;
+       bool can_read = TRUE;
 
        if (!view->pipe)
                return TRUE;
 
+       if (!io_can_read(view->pipe))
+               return TRUE;
+
        /* Only redraw if lines are visible. */
        if (view->offset + view->height >= view->lines)
                redraw_from = view->lines - view->offset;
 
-       /* FIXME: This is probably not perfect for backgrounded views. */
-       if (!realloc_lines(view, view->lines + lines))
-               goto alloc_error;
-
-       while ((line = io_get(view->pipe, '\n', TRUE))) {
+       for (; (line = io_get(view->pipe, '\n', can_read)); can_read = FALSE) {
                size_t linelen = strlen(line);
 
                if (opt_iconv != ICONV_NONE) {
@@ -2702,17 +2711,15 @@ update_view(struct view *view)
                        }
                }
 
-               if (!view->ops->read(view, line))
+               if (!realloc_lines(view, view->lines + 1) ||
+                   !view->ops->read(view, line))
                        goto alloc_error;
-
-               if (lines-- == 1)
-                       break;
        }
 
        {
+               unsigned long lines = view->lines;
                int digits;
 
-               lines = view->lines;
                for (digits = 0; lines; digits++)
                        lines /= 10;