diff options
author | bfredl <bjorn.linse@gmail.com> | 2023-04-23 19:02:23 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2023-04-24 17:38:19 +0200 |
commit | 0d2fe7786537ef63d0d3ed1e94546eb3ee35a368 (patch) | |
tree | f479da09da4436af82dc015646ab519556c81750 /src/nvim/os/time.c | |
parent | 3ac952d4e27f4e2454332a730310316fe13fd4a3 (diff) | |
download | rneovim-0d2fe7786537ef63d0d3ed1e94546eb3ee35a368.tar.gz rneovim-0d2fe7786537ef63d0d3ed1e94546eb3ee35a368.tar.bz2 rneovim-0d2fe7786537ef63d0d3ed1e94546eb3ee35a368.zip |
refactor(time): refactor delay with input checking
Previously, there were three low-level delay entry points
- os_delay(ms, ignoreinput=true): sleep for ms, only break on got_int
- os_delay(ms, ignoreinput=false): sleep for ms, break on any key input
os_microdelay(us, false): equivalent, but in μs (not directly called)
- os_microdelay(us, true): sleep for μs, never break.
The implementation of the latter two both used uv_cond_timedwait()
This could have been for two reasons:
1. allow another thread to "interrupt" the wait
2. uv_cond_timedwait() has higher resolution than uv_sleep()
However we (1) never used the first, even when TUI was a thread, and
(2) nowhere in the codebase are we using μs resolution, it is always a ms
multiplied with 1000.
In addition, os_delay(ms, false) would completely block the thread for
100ms intervals and in between check for input. This is not how event handling
is done alound here.
Therefore:
Replace the implementation of os_delay(ms, false) to use
LOOP_PROCESS_EVENTS_UNTIL which does a proper epoll wait with a timeout,
instead of the 100ms timer panic.
Replace os_microdelay(us, false) with a direct wrapper of uv_sleep.
Diffstat (limited to 'src/nvim/os/time.c')
-rw-r--r-- | src/nvim/os/time.c | 63 |
1 files changed, 13 insertions, 50 deletions
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 873302a27d..8d77e58177 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -24,20 +24,10 @@ struct tm; -static uv_mutex_t delay_mutex; -static uv_cond_t delay_cond; - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "os/time.c.generated.h" // IWYU pragma: export #endif -/// Initializes the time module -void time_init(void) -{ - uv_mutex_init(&delay_mutex); - uv_cond_init(&delay_cond); -} - /// Gets a high-resolution (nanosecond), monotonically-increasing time relative /// to an arbitrary time in the past. /// @@ -73,55 +63,28 @@ uint64_t os_now(void) void os_delay(uint64_t ms, bool ignoreinput) { DLOG("%" PRIu64 " ms", ms); - if (ignoreinput) { - if (ms > INT_MAX) { - ms = INT_MAX; - } - LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)ms, got_int); - } else { - os_microdelay(ms * 1000U, ignoreinput); + if (ms > INT_MAX) { + ms = INT_MAX; } + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)ms, + ignoreinput ? got_int : os_input_ready(NULL)); } -/// Sleeps for `us` microseconds. +/// Sleeps for `ms` milliseconds without checking for events or interrupts. +/// +/// This blocks even "fast" events which is quite disruptive. This should only +/// be used in debug code. Prefer os_delay() and decide if the delay should be +/// interupted by input or only a CTRL-C. /// /// @see uv_sleep() (libuv v1.34.0) /// /// @param us Number of microseconds to sleep. -/// @param ignoreinput If true, ignore all input (including SIGINT/CTRL-C). -/// If false, waiting is aborted on any input. -void os_microdelay(uint64_t us, bool ignoreinput) +void os_sleep(uint64_t ms) { - uint64_t elapsed = 0U; - uint64_t base = uv_hrtime(); - // Convert microseconds to nanoseconds, or UINT64_MAX on overflow. - const uint64_t ns = (us < UINT64_MAX / 1000U) ? us * 1000U : UINT64_MAX; - - uv_mutex_lock(&delay_mutex); - - while (elapsed < ns) { - // If ignoring input, we simply wait the full delay. - // Else we check for input in ~100ms intervals. - const uint64_t ns_delta = ignoreinput - ? ns - elapsed - : MIN(ns - elapsed, 100000000U); // 100ms - - const int rv = uv_cond_timedwait(&delay_cond, &delay_mutex, ns_delta); - if (0 != rv && UV_ETIMEDOUT != rv) { - abort(); - break; - } // Else: Timeout proceeded normally. - - if (!ignoreinput && os_char_avail()) { - break; - } - - const uint64_t now = uv_hrtime(); - elapsed += now - base; - base = now; + if (ms > UINT_MAX) { + ms = UINT_MAX; } - - uv_mutex_unlock(&delay_mutex); + uv_sleep((unsigned)ms); } // Cache of the current timezone name as retrieved from TZ, or an empty string |