From 15c7c6c11c07e3b8697e0088936ee15eda2860ed Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 27 Aug 2019 23:12:04 -0700 Subject: [PATCH 1/2] term: minor refactoring of write patterns --- pkg/urbit/vere/term.c | 37 +++++++++++++++---------------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/pkg/urbit/vere/term.c b/pkg/urbit/vere/term.c index fa79c70c3e..4d76fa9eae 100644 --- a/pkg/urbit/vere/term.c +++ b/pkg/urbit/vere/term.c @@ -28,15 +28,17 @@ static c3_i _term_tcsetattr(int, int, const struct termios *); #define _SPIN_RATE_US 250000 // spinner rate (microseconds/frame) #define _SPIN_IDLE_US 500000 // spinner cools down if stopped this long -static void _write(int fd, const void *buf, size_t count) +/* _write(): wraps write(), asserting length +*/ +static void +_write(c3_i fid_i, const void* buf_v, size_t len) { - if (count != write(fd, buf, count)){ + if ( len != write(fid_i, buf_v, len) ){ u3l_log("write failed\r\n"); c3_assert(0); } } - /* _term_msc_out_host(): unix microseconds from current host time. */ static c3_d @@ -288,7 +290,7 @@ void u3_term_io_exit(void) { if ( c3y == u3_Host.ops_u.dem ) { - uv_close((uv_handle_t*)&u3_Host.uty_u->pop_u, NULL); + uv_close((uv_handle_t*)&u3_Host.uty_u->pop_u, 0); } else { u3_utty* uty_u; @@ -353,25 +355,17 @@ _term_it_buf(c3_w len_w, const c3_y* hun_y) return buf_u; } -/* An unusual lameness in libuv. -*/ - typedef struct { - uv_write_t wri_u; - c3_y* buf_y; - } _u3_write_t; - /* _term_write_cb(): general write callback. */ static void _term_write_cb(uv_write_t* wri_u, c3_i sas_i) { - _u3_write_t* ruq_u = (void *)wri_u; - if ( 0 != sas_i ) { - // u3l_log("term: write: ERROR\n"); + u3l_log("term: write: %s\n", uv_strerror(sas_i)); } - free(ruq_u->buf_y); - free(ruq_u); + + free(wri_u->data); + free(wri_u); } /* _term_it_write_buf(): write buffer uv style. @@ -379,17 +373,16 @@ _term_write_cb(uv_write_t* wri_u, c3_i sas_i) static void _term_it_write_buf(u3_utty* uty_u, uv_buf_t buf_u) { - _u3_write_t* ruq_u = (_u3_write_t*) c3_malloc(sizeof(_u3_write_t)); - - ruq_u->buf_y = (c3_y*)buf_u.base; + uv_write_t* wri_u = c3_malloc(sizeof(uv_write_t)); + wri_u->data = buf_u.base; c3_w ret_w; - if ( 0 != (ret_w = uv_write(&ruq_u->wri_u, + if ( 0 != (ret_w = uv_write(wri_u, (uv_stream_t*)&(uty_u->pop_u), &buf_u, 1, - _term_write_cb)) ) + _term_write_cb)) ) { - u3l_log("terminal: %s\n", uv_strerror(ret_w)); + u3l_log("term: write: %s\n", uv_strerror(ret_w)); } } From b2a7e8c30d2f3537452cd1a331236e5115abfca5 Mon Sep 17 00:00:00 2001 From: Joe Bryan Date: Tue, 27 Aug 2019 23:14:40 -0700 Subject: [PATCH 2/2] term: rewrites spinner, renders on main loop --- pkg/urbit/include/vere/vere.h | 16 +- pkg/urbit/vere/pier.c | 60 ++++++-- pkg/urbit/vere/term.c | 270 ++++++++++------------------------ 3 files changed, 136 insertions(+), 210 deletions(-) diff --git a/pkg/urbit/include/vere/vere.h b/pkg/urbit/include/vere/vere.h index b7fe799ecd..226cd4362c 100644 --- a/pkg/urbit/include/vere/vere.h +++ b/pkg/urbit/include/vere/vere.h @@ -384,14 +384,12 @@ } fut; struct { - uv_thread_t* sit_u; // spinner thread - c3_o diz_o; // spinner activated - c3_d eve_d; // spinner start tick (unix μs) - c3_d end_d; // spinner end tick (unix μs) - c3_c* why_c; // spinner event wire (root only) - } sun; - - uv_mutex_t mex_u; // mutex for non-daemon term state + uv_timer_t tim_u; // spinner timeout + c3_o diz_o; // spinner activated + c3_d eve_d; // spin count + c3_d end_d; // spinner end tick (ms) + c3_c* why_c; // spinner label + } sun_u; } u3_utat; struct _u3_umon; @@ -871,7 +869,7 @@ /* u3_term_start_spinner(): prepare spinner state. RETAIN. */ void - u3_term_start_spinner(u3_noun ovo); + u3_term_start_spinner(c3_c* why_c, c3_o now_o); /* u3_term_stop_spinner(): reset spinner state and restore input line. */ diff --git a/pkg/urbit/vere/pier.c b/pkg/urbit/vere/pier.c index 2bac7f09cc..1d5db4bfe1 100644 --- a/pkg/urbit/vere/pier.c +++ b/pkg/urbit/vere/pier.c @@ -658,6 +658,54 @@ _pier_work_release(u3_writ* wit_u) } } +/* _pier_work_spin_start(): activate spinner. +*/ +static void +_pier_work_spin_start(u3_writ* wit_u) +{ + u3_pier* pir_u = wit_u->pir_u; + c3_o now_o = c3n; + c3_c* why_c = 0; + + if ( wit_u->evt_d <= pir_u->lif_d ) { + why_c = strdup("nock"); + } + else { + u3_noun why; + + // second item of the event wire + // + // i.t.p.q:*(pair @da ovum) + // + if ( u3_none != (why = u3r_at(26, wit_u->job)) ) { + u3_noun cad, tag, lag; + + + if ( c3__term != why ) { + why_c = u3r_string(why); + } + else if ( ( u3_none != (cad = u3r_at(7, wit_u->job)) ) && + ( u3_none != (tag = u3r_at(2, cad)) ) && + ( u3_none != (lag = u3r_at(6, cad)) ) && + ( c3__belt == tag ) && + ( c3__ret == lag ) ) + { + now_o = c3y; + } + } + } + + u3_term_start_spinner(why_c, now_o); +} + +/* _pier_work_spin_stop(): deactivate spinner. +*/ +static void +_pier_work_spin_stop(u3_writ* wit_u) +{ + u3_term_stop_spinner(); +} + /* _pier_work_complete(): worker reported completion. */ static void @@ -680,9 +728,7 @@ _pier_work_complete(u3_writ* wit_u, c3_assert(wit_u->act == 0); wit_u->act = act; - if ( wit_u->evt_d > pir_u->lif_d ) { - u3_term_stop_spinner(); - } + _pier_work_spin_stop(wit_u); } /* _pier_work_replace(): worker reported replacement. @@ -720,9 +766,7 @@ _pier_work_replace(u3_writ* wit_u, god_u->sen_d -= 1ULL; } - if ( wit_u->evt_d > pir_u->lif_d ) { - u3_term_stop_spinner(); - } + _pier_work_spin_stop(wit_u); } /* _pier_work_compute(): dispatch for processing. @@ -746,9 +790,7 @@ _pier_work_compute(u3_writ* wit_u) god_u->sen_d += 1; - if ( wit_u->evt_d > pir_u->lif_d ) { - u3_term_start_spinner(wit_u->job); - } + _pier_work_spin_start(wit_u); } /* _pier_work_play(): with active worker, create or load log. diff --git a/pkg/urbit/vere/term.c b/pkg/urbit/vere/term.c index 4d76fa9eae..4d35639ee4 100644 --- a/pkg/urbit/vere/term.c +++ b/pkg/urbit/vere/term.c @@ -15,18 +15,11 @@ #include "all.h" #include "vere/vere.h" -static void _term_spinner_cb(void*); -static void _term_read_cb(uv_stream_t* tcp_u, - ssize_t siz_i, - const uv_buf_t * buf_u); -static inline void _term_suck(u3_utty*, const c3_y*, ssize_t); static u3_utty* _term_main(); -static c3_i _term_tcsetattr(int, int, const struct termios *); - -#define _SPIN_COOL_US 500000 // spinner activation delay when cool -#define _SPIN_WARM_US 50000 // spinner activation delay when warm -#define _SPIN_RATE_US 250000 // spinner rate (microseconds/frame) -#define _SPIN_IDLE_US 500000 // spinner cools down if stopped this long +static void _term_read_cb(uv_stream_t* tcp_u, + ssize_t siz_i, + const uv_buf_t* buf_u); +static c3_i _term_tcsetattr(int, int, const struct termios *); /* _write(): wraps write(), asserting length */ @@ -256,25 +249,11 @@ u3_term_io_init() } } - // Start spinner thread. + // initialize spinner timeout (if not in daemon-mode) // - { - uty_u->tat_u.sun.sit_u = (uv_thread_t*)malloc(sizeof(uv_thread_t)); - if ( uty_u->tat_u.sun.sit_u ) { - uv_mutex_init(&uty_u->tat_u.mex_u); - uv_mutex_lock(&uty_u->tat_u.mex_u); - - c3_w ret_w = uv_thread_create(uty_u->tat_u.sun.sit_u, - _term_spinner_cb, - uty_u); - if ( 0 != ret_w ) { - u3l_log("term: spinner start: %s\n", uv_strerror(ret_w)); - free(uty_u->tat_u.sun.sit_u); - uty_u->tat_u.sun.sit_u = NULL; - uv_mutex_unlock(&uty_u->tat_u.mex_u); - uv_mutex_destroy(&uty_u->tat_u.mex_u); - } - } + if ( c3n == u3_Host.ops_u.dem ) { + uv_timer_init(u3L, &uty_u->tat_u.sun_u.tim_u); + uty_u->tat_u.sun_u.tim_u.data = uty_u; } } } @@ -305,25 +284,7 @@ u3_term_io_exit(void) } _write(uty_u->fid_i, "\r\n", 2); -#if 0 - if ( uty_u->tat_u.sun.sit_u ) { - uv_thread_t* sit_u = uty_u->tat_u.sun.sit_u; - uty_u->tat_u.sun.sit_u = NULL; - - uv_mutex_unlock(&uty_u->tat_u.mex_u); - - // XX can block exit waiting for wakeup (max _SPIN_COOL_US) - c3_w ret_w; - if ( 0 != (ret_w = uv_thread_join(sit_u)) ) { - u3l_log("term: spinner exit: %s\n", uv_strerror(ret_w)); - } - else { - uv_mutex_destroy(&uty_u->tat_u.mex_u); - } - - free(sit_u); - } -#endif + uv_close((uv_handle_t*)&uty_u->tat_u.sun_u.tim_u, 0); } } } @@ -773,11 +734,11 @@ _term_read_cb(uv_stream_t* tcp_u, free(buf_u->base); } -/* _term_try_write_str(): write null-terminated string (off-thread, retain). +/* _term_spin_write_str(): write null-terminated string */ static void -_term_try_write_str(u3_utty* uty_u, - const c3_c* str_c) +_term_spin_write_str(u3_utty* uty_u, + const c3_c* str_c) { // c3_i fid_i = uv_fileno(&uty_u->pop_u); c3_i fid_i = uty_u->pop_u.io_watcher.fd; // XX old libuv @@ -788,30 +749,31 @@ _term_try_write_str(u3_utty* uty_u, } } -/* _term_try_move_left(): move the cursor left (off-thread). +/* _term_spin_move_left(): move the cursor left */ static void -_term_try_move_left(u3_utty* uty_u) +_term_spin_move_left(u3_utty* uty_u) { - _term_try_write_str(uty_u, (const c3_c*)uty_u->ufo_u.out.cub1_y); + _term_spin_write_str(uty_u, (const c3_c*)uty_u->ufo_u.out.cub1_y); } -/* _term_show_spinner(): render spinner (off-thread). +/* _term_spin_timer_cb(): render spinner */ static void -_term_show_spinner(u3_utty* uty_u, c3_d lag_d) +_term_spin_timer_cb(uv_timer_t* tim_u) { - if ( 0 == uty_u->tat_u.sun.eve_d ) { + u3_utty* uty_u = tim_u->data; + u3_utat* tat_u = &uty_u->tat_u; + + c3_w cus_w = tat_u->mir.cus_w; + c3_l col_l = tat_u->siz.col_l; + + if ( cus_w >= col_l ) { // shenanigans! return; } - c3_w cus_w = uty_u->tat_u.mir.cus_w; - - if ( cus_w >= uty_u->tat_u.siz.col_l ) { // shenanigans! - return; - } - - c3_w bac_w = uty_u->tat_u.siz.col_l - 1 - cus_w; // backoff from end of line + c3_w bac_w = col_l - 1 - cus_w; // backoff from end of line + c3_d lag_d = tat_u->sun_u.eve_d++; const c3_c daz_c[] = "|/-\\"; const c3_c dal_c[] = "\xc2\xab"; @@ -822,109 +784,75 @@ _term_show_spinner(u3_utty* uty_u, c3_d lag_d) c3_c* cur_c = buf_c; - *cur_c++ = daz_c[(lag_d / _SPIN_RATE_US) % strlen(daz_c)]; + *cur_c++ = daz_c[lag_d % strlen(daz_c)]; c3_w sol_w = 1; // spinner length (utf-32) - c3_c* why_c = uty_u->tat_u.sun.why_c; - if ( why_c && strlen(why_c) <= 4 ) { - strcpy(cur_c, dal_c); - cur_c += strlen(dal_c); + if ( tat_u->sun_u.why_c ) { + strncpy(cur_c, dal_c, 2); + cur_c += 2; sol_w += 1; // length of dal_c (utf-32) - c3_w wel_w = strlen(why_c); - strcpy(cur_c, why_c); - cur_c += wel_w; - sol_w += wel_w; + // c3_w wel_w = strlen(tat_u.sun_u->why_c); + strncpy(cur_c, tat_u->sun_u.why_c, 4); + cur_c += 4; + sol_w += 4; // XX assumed utf-8 - strcpy(cur_c, dar_c); - cur_c += strlen(dar_c); + strncpy(cur_c, dar_c, 2); + cur_c += 2; sol_w += 1; // length of dar_c (utf-32) } + *cur_c = '\0'; - // One-time cursor backoff. - if ( c3n == uty_u->tat_u.sun.diz_o ) { + // One-time cursor backoff. + if ( c3n == tat_u->sun_u.diz_o ) { c3_w i_w; for ( i_w = bac_w; i_w < sol_w; i_w++ ) { - _term_try_move_left(uty_u); + _term_spin_move_left(uty_u); } } - _term_try_write_str(uty_u, buf_c); - uty_u->tat_u.sun.diz_o = c3y; + _term_spin_write_str(uty_u, buf_c); + tat_u->sun_u.diz_o = c3y; // Cursor stays on spinner. while ( sol_w-- ) { - _term_try_move_left(uty_u); + _term_spin_move_left(uty_u); } } -/* _term_start_spinner(): prepare spinner state. RETAIN. -*/ -static void -_term_start_spinner(u3_utty* uty_u, u3_noun ovo) -{ - uty_u->tat_u.sun.diz_o = c3n; +#define _SPIN_COOL_US 500UL // spinner activation delay when cool +#define _SPIN_WARM_US 50UL // spinner activation delay when warm +#define _SPIN_RATE_US 250UL // spinner rate (ms/frame) +#define _SPIN_IDLE_US 500UL // spinner cools down if stopped this long - c3_d now_d = _term_msc_out_host(); - - // If we receive an event shortly after a previous spin, use a shorter delay - // to avoid giving the impression of a half-idle system. - // - c3_d lag_d; - if ( now_d - uty_u->tat_u.sun.end_d < _SPIN_IDLE_US ) { - lag_d = _SPIN_WARM_US; - } - else { - lag_d = _SPIN_COOL_US; - } - - // second item of the event wire - // - u3_noun why = u3h(u3t(u3h(u3t(ovo)))); - if ( c3__term == why ) { - u3_noun eve = u3t(u3t(ovo)); - if ( c3__belt == u3h(eve) && c3__ret == u3h(u3t(eve)) ) { - lag_d = 0; // No delay for %ret. - } - } - else { - uty_u->tat_u.sun.why_c = (c3_c*)u3r_string(why); - } - - uty_u->tat_u.sun.eve_d = now_d + lag_d; - - uv_mutex_unlock(&uty_u->tat_u.mex_u); -} - -/* u3_term_stop_spinner(): reset spinner state and restore input line. -*/ -static void -_term_stop_spinner(u3_utty* uty_u) -{ - uv_mutex_lock(&uty_u->tat_u.mex_u); - - if ( c3y == uty_u->tat_u.sun.diz_o ) { - _term_it_refresh_line(uty_u); - uty_u->tat_u.sun.end_d = _term_msc_out_host(); - } - else { - uty_u->tat_u.sun.end_d = 0; - } - - uty_u->tat_u.sun.diz_o = c3n; - uty_u->tat_u.sun.eve_d = 0; - free(uty_u->tat_u.sun.why_c); - uty_u->tat_u.sun.why_c = NULL; -} - -/* u3_term_start_spinner(): prepare spinner state. RETAIN. +/* u3_term_start_spinner(): prepare spinner state */ void -u3_term_start_spinner(u3_noun ovo) +u3_term_start_spinner(c3_c* why_c, c3_o now_o) { if ( c3n == u3_Host.ops_u.dem ) { - _term_start_spinner(_term_main(), ovo); + u3_utty* uty_u = _term_main(); + u3_utat* tat_u = &uty_u->tat_u; + + free(tat_u-> sun_u.why_c); + tat_u->sun_u.why_c = why_c; + + tat_u->sun_u.eve_d = 0; + // XX must be c3n for cursor backoff from EOL? + tat_u->sun_u.diz_o = c3n; + + { + c3_d now_d = _term_msc_out_host(); + c3_d end_d = tat_u->sun_u.end_d; + c3_d wen_d = (c3y == now_o) ? 0UL : + (now_d - end_d < _SPIN_IDLE_US) ? + _SPIN_WARM_US : _SPIN_COOL_US; + + uv_timer_start(&tat_u->sun_u.tim_u, + _term_spin_timer_cb, + wen_d, _SPIN_RATE_US); + } } } @@ -934,52 +862,20 @@ void u3_term_stop_spinner(void) { if ( c3n == u3_Host.ops_u.dem ) { - _term_stop_spinner(_term_main()); - } -} + u3_utty* uty_u = _term_main(); + u3_utat* tat_u = &uty_u->tat_u; -/* _term_spinner_cb(): manage spinner (off-thread). -*/ -static void -_term_spinner_cb(void* ptr_v) -{ - // This thread shouldn't receive signals. - // - { - sigset_t set; - sigfillset(&set); - pthread_sigmask(SIG_BLOCK, &set, NULL); - } + uv_timer_stop(&tat_u->sun_u.tim_u); - u3_utty* uty_u = (u3_utty*)ptr_v; - - for ( uv_mutex_lock(&uty_u->tat_u.mex_u); - uty_u->tat_u.sun.sit_u; - uv_mutex_lock(&uty_u->tat_u.mex_u) ) - { - c3_d eve_d = uty_u->tat_u.sun.eve_d; - - if ( 0 == eve_d ) { - c3_o diz_o = uty_u->tat_u.sun.diz_o; - uv_mutex_unlock(&uty_u->tat_u.mex_u); - usleep(c3y == diz_o ? _SPIN_WARM_US : _SPIN_COOL_US); + if ( c3y == tat_u->sun_u.diz_o ) { + _term_it_refresh_line(uty_u); + tat_u->sun_u.end_d = _term_msc_out_host(); + tat_u->sun_u.diz_o = c3n; } else { - c3_d now_d = _term_msc_out_host(); - - if (now_d < eve_d) { - uv_mutex_unlock(&uty_u->tat_u.mex_u); - usleep(eve_d - now_d); - } - else { - _term_show_spinner(uty_u, now_d - eve_d); - uv_mutex_unlock(&uty_u->tat_u.mex_u); - usleep(_SPIN_RATE_US); - } + tat_u->sun_u.end_d = 0; } } - - uv_mutex_unlock(&uty_u->tat_u.mex_u); } /* _term_main(): return main or console terminal. @@ -1093,16 +989,6 @@ _term_ef_blit(u3_utty* uty_u, { switch ( u3h(blt) ) { default: break; - case c3__bee: { - if ( c3n == u3_Host.ops_u.dem ) { - if ( u3_nul == u3t(blt) ) { - _term_stop_spinner(uty_u); - } - else { - _term_start_spinner(uty_u, u3t(blt)); - } - } - } break; case c3__bel: { if ( c3n == u3_Host.ops_u.dem ) {