diff options
Diffstat (limited to 'src/nvim/os/time.c')
-rw-r--r-- | src/nvim/os/time.c | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c index 2205ad0958..31ef1a0cd6 100644 --- a/src/nvim/os/time.c +++ b/src/nvim/os/time.c @@ -1,3 +1,6 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #include <assert.h> #include <stdint.h> #include <stdbool.h> @@ -7,6 +10,7 @@ #include <uv.h> #include "nvim/os/time.h" +#include "nvim/os/input.h" #include "nvim/event/loop.h" #include "nvim/vim.h" #include "nvim/main.h" @@ -34,38 +38,54 @@ uint64_t os_hrtime(void) return uv_hrtime(); } -/// Sleeps for a certain amount of milliseconds +/// Sleeps for `ms` milliseconds. /// -/// @param milliseconds Number of milliseconds to sleep -/// @param ignoreinput If true, allow a SIGINT to interrupt us -void os_delay(uint64_t milliseconds, bool ignoreinput) +/// @param ms Number of milliseconds to sleep +/// @param ignoreinput If true, only SIGINT (CTRL-C) can interrupt. +void os_delay(uint64_t ms, bool ignoreinput) { if (ignoreinput) { - if (milliseconds > INT_MAX) { - milliseconds = INT_MAX; + if (ms > INT_MAX) { + ms = INT_MAX; } - LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)milliseconds, got_int); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, NULL, (int)ms, got_int); } else { - os_microdelay(milliseconds * 1000); + os_microdelay(ms * 1000u, ignoreinput); } } -/// Sleeps for a certain amount of microseconds +/// Sleeps for `us` microseconds. /// -/// @param microseconds Number of microseconds to sleep -void os_microdelay(uint64_t microseconds) +/// @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) { - uint64_t elapsed = 0; - uint64_t ns = microseconds * 1000; // convert to nanoseconds + 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 (uv_cond_timedwait(&delay_cond, &delay_mutex, ns - elapsed) - == UV_ETIMEDOUT) + // 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) { + assert(false); + break; + } // Else: Timeout proceeded normally. + + if (!ignoreinput && os_char_avail()) { break; - uint64_t now = uv_hrtime(); + } + + const uint64_t now = uv_hrtime(); elapsed += now - base; base = now; } @@ -94,12 +114,12 @@ struct tm *os_localtime_r(const time_t *restrict clock, #endif } -/// Obtains the current Unix timestamp and adjusts it to local time. +/// Gets the current Unix timestamp and adjusts it to local time. /// /// @param result Pointer to a 'struct tm' where the result should be placed /// @return A pointer to a 'struct tm' in the current time zone (the 'result' /// argument) or NULL in case of error -struct tm *os_get_localtime(struct tm *result) FUNC_ATTR_NONNULL_ALL +struct tm *os_localtime(struct tm *result) FUNC_ATTR_NONNULL_ALL { time_t rawtime = time(NULL); return os_localtime_r(&rawtime, result); |