mirror of
https://github.com/neovim/neovim.git
synced 2026-08-29 10:31:48 +00:00
api: nvim_get_mode()
Asynchronous API functions are served immediately, which means pending
input could change the state of Nvim shortly after an async API function
result is returned.
nvim_get_mode() is different:
- If RPCs are known to be blocked, it responds immediately (without
flushing the input/event queue)
- else it is handled just-in-time before waiting for input, after
pending input was processed. This makes the result more reliable
(but not perfect).
Internally this is handled as a special case, but _semantically_ nothing
has changed: API users never know when input flushes, so this internal
special-case doesn't violate that. As far as API users are concerned,
nvim_get_mode() is just another asynchronous API function.
In all cases nvim_get_mode() never blocks for more than the time it
takes to flush the input/event queue (~µs).
Note: This doesn't address #6166; nvim_get_mode() will provoke #6166 if
e.g. `d` is operator-pending.
Closes #6159
This commit is contained in:
@@ -44,8 +44,7 @@ void loop_poll_events(Loop *loop, int ms)
|
||||
// we do not block indefinitely for I/O.
|
||||
uv_timer_start(&loop->poll_timer, timer_cb, (uint64_t)ms, (uint64_t)ms);
|
||||
} else if (ms == 0) {
|
||||
// For ms == 0, we need to do a non-blocking event poll by
|
||||
// setting the run mode to UV_RUN_NOWAIT.
|
||||
// For ms == 0, do a non-blocking event poll.
|
||||
mode = UV_RUN_NOWAIT;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
|
||||
#include "nvim/event/multiqueue.h"
|
||||
#include "nvim/memory.h"
|
||||
#include "nvim/log.h"
|
||||
#include "nvim/os/time.h"
|
||||
|
||||
typedef struct multiqueue_item MultiQueueItem;
|
||||
@@ -151,6 +152,40 @@ void multiqueue_process_events(MultiQueue *this)
|
||||
}
|
||||
}
|
||||
|
||||
void multiqueue_process_debug(MultiQueue *this)
|
||||
{
|
||||
assert(this);
|
||||
QUEUE *start = QUEUE_HEAD(&this->headtail);
|
||||
QUEUE *cur = start;
|
||||
// MultiQueue *start = this;
|
||||
// MultiQueue *cur = start;
|
||||
do {
|
||||
MultiQueueItem *item = multiqueue_node_data(cur);
|
||||
Event ev;
|
||||
if (item->link) {
|
||||
assert(!this->parent);
|
||||
// get the next node in the linked queue
|
||||
MultiQueue *linked = item->data.queue;
|
||||
assert(!multiqueue_empty(linked));
|
||||
MultiQueueItem *child =
|
||||
multiqueue_node_data(QUEUE_HEAD(&linked->headtail));
|
||||
ev = child->data.item.event;
|
||||
} else {
|
||||
ev = item->data.item.event;
|
||||
}
|
||||
|
||||
// Event event = multiqueue_get(this);
|
||||
// if (event.handler) {
|
||||
// event.handler(event.argv);
|
||||
// }
|
||||
|
||||
ILOG("ev: priority=%d, handler=%p arg1=%s", ev.priority, ev.handler,
|
||||
ev.argv ? ev.argv[0] : "(null)");
|
||||
|
||||
cur = cur->next;
|
||||
} while (cur && cur != start);
|
||||
}
|
||||
|
||||
/// Removes all events without processing them.
|
||||
void multiqueue_purge_events(MultiQueue *this)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user