diff options
author | nicm <nicm> | 2015-05-12 22:40:38 +0000 |
---|---|---|
committer | nicm <nicm> | 2015-05-12 22:40:38 +0000 |
commit | 3f4ee98162cd5bb7000f93fec0e631e123b1281d (patch) | |
tree | 07d42ed7718f737c364d5afc9d825a4e553c81d7 /window.c | |
parent | 37ae8a9e0fc2cd7ab2387a9a762a39dc0ff6723c (diff) | |
download | rtmux-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.c | 56 |
1 files changed, 48 insertions, 8 deletions
@@ -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; |