aboutsummaryrefslogtreecommitdiff
path: root/window.c
diff options
context:
space:
mode:
authornicm <nicm>2015-05-12 22:40:38 +0000
committernicm <nicm>2015-05-12 22:40:38 +0000
commit3f4ee98162cd5bb7000f93fec0e631e123b1281d (patch)
tree07d42ed7718f737c364d5afc9d825a4e553c81d7 /window.c
parent37ae8a9e0fc2cd7ab2387a9a762a39dc0ff6723c (diff)
downloadrtmux-3f4ee98162cd5bb7000f93fec0e631e123b1281d.tar.gz
rtmux-3f4ee98162cd5bb7000f93fec0e631e123b1281d.tar.bz2
rtmux-3f4ee98162cd5bb7000f93fec0e631e123b1281d.zip
To replace c0-*, add a high watermark to the pty event, and also backoff
when the any of the ttys the pane is going to write to has buffered enough data.
Diffstat (limited to 'window.c')
-rw-r--r--window.c56
1 files changed, 48 insertions, 8 deletions
diff --git a/window.c b/window.c
index 7edfed42..bc17656d 100644
--- a/window.c
+++ b/window.c
@@ -58,6 +58,7 @@ u_int next_window_pane_id;
u_int next_window_id;
u_int next_active_point;
+void window_pane_timer_callback(int, short, void *);
void window_pane_read_callback(struct bufferevent *, void *);
void window_pane_error_callback(struct bufferevent *, short, void *);
@@ -740,6 +741,9 @@ window_pane_destroy(struct window_pane *wp)
{
window_pane_reset_mode(wp);
+ if (event_initialized(&wp->timer))
+ evtimer_del(&wp->timer);
+
if (wp->fd != -1) {
bufferevent_free(wp->event);
close(wp->fd);
@@ -867,6 +871,8 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
wp->event = bufferevent_new(wp->fd, window_pane_read_callback, NULL,
window_pane_error_callback, wp);
+
+ bufferevent_setwatermark(wp->event, EV_READ, 0, READ_SIZE);
bufferevent_enable(wp->event, EV_READ|EV_WRITE);
free(cmd);
@@ -874,21 +880,44 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
}
void
+window_pane_timer_callback(unused int fd, unused short events, void *data)
+{
+ window_pane_read_callback(NULL, data);
+}
+
+void
window_pane_read_callback(unused struct bufferevent *bufev, void *data)
{
- struct window_pane *wp = data;
- char *new_data;
- size_t new_size;
+ struct window_pane *wp = data;
+ struct evbuffer *evb = wp->event->input;
+ char *new_data;
+ size_t new_size, available;
+ struct client *c;
+ struct timeval tv;
+
+ if (event_initialized(&wp->timer))
+ evtimer_del(&wp->timer);
+
+ log_debug("%%%u has %zu bytes", wp->id, EVBUFFER_LENGTH(evb));
- new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
+ TAILQ_FOREACH(c, &clients, entry) {
+ if (!tty_client_ready(c, wp))
+ continue;
+
+ available = EVBUFFER_LENGTH(c->tty.event->output);
+ if (available > READ_BACKOFF)
+ goto start_timer;
+ }
+
+ new_size = EVBUFFER_LENGTH(evb) - wp->pipe_off;
if (wp->pipe_fd != -1 && new_size > 0) {
- new_data = EVBUFFER_DATA(wp->event->input);
+ new_data = EVBUFFER_DATA(evb);
bufferevent_write(wp->pipe_event, new_data, new_size);
}
input_parse(wp);
- wp->pipe_off = EVBUFFER_LENGTH(wp->event->input);
+ wp->pipe_off = EVBUFFER_LENGTH(evb);
/*
* If we get here, we're not outputting anymore, so set the silence
@@ -897,11 +926,22 @@ window_pane_read_callback(unused struct bufferevent *bufev, void *data)
wp->window->flags |= WINDOW_SILENCE;
if (gettimeofday(&wp->window->silence_timer, NULL) != 0)
fatal("gettimeofday failed.");
+ return;
+
+start_timer:
+ log_debug("%%%u backing off (%s %zu > %d)", wp->id, c->ttyname,
+ available, READ_BACKOFF);
+
+ tv.tv_sec = 0;
+ tv.tv_usec = READ_TIME;
+
+ evtimer_set(&wp->timer, window_pane_timer_callback, wp);
+ evtimer_add(&wp->timer, &tv);
}
void
-window_pane_error_callback(
- unused struct bufferevent *bufev, unused short what, void *data)
+window_pane_error_callback(unused struct bufferevent *bufev, unused short what,
+ void *data)
{
struct window_pane *wp = data;