aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/time.c
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2023-04-23 19:02:23 +0200
committerbfredl <bjorn.linse@gmail.com>2023-04-24 17:38:19 +0200
commit0d2fe7786537ef63d0d3ed1e94546eb3ee35a368 (patch)
treef479da09da4436af82dc015646ab519556c81750 /src/nvim/os/time.c
parent3ac952d4e27f4e2454332a730310316fe13fd4a3 (diff)
downloadrneovim-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.c63
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