aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c78
1 files changed, 36 insertions, 42 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index e2f095dbad..d61cccd41c 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -468,6 +468,7 @@ typedef struct {
dict_T *self;
int *status_ptr;
uint64_t id;
+ Queue *events;
} TerminalJobData;
/// Structure representing current VimL to messagepack conversion state
@@ -493,6 +494,13 @@ typedef struct {
/// Stack used to convert VimL values to messagepack.
typedef kvec_t(MPConvStackVal) MPConvStack;
+typedef struct {
+ TerminalJobData *data;
+ ufunc_T *callback;
+ const char *type;
+ list_T *received;
+ int status;
+} JobEvent;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval.c.generated.h"
@@ -501,15 +509,6 @@ typedef kvec_t(MPConvStackVal) MPConvStack;
#define FNE_INCL_BR 1 /* find_name_end(): include [] in name */
#define FNE_CHECK_START 2 /* find_name_end(): check name starts with
valid character */
-// Memory pool for reusing JobEvent structures
-typedef struct {
- TerminalJobData *data;
- ufunc_T *callback;
- const char *type;
- list_T *received;
- int status;
-} JobEvent;
-static int disable_job_defer = 0;
static uint64_t current_job_id = 1;
static PMap(uint64_t) *jobs = NULL;
@@ -11038,15 +11037,6 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
list_T *rv = list_alloc();
ui_busy_start();
- // disable breakchecks, which could result in job callbacks being executed
- // at unexpected places
- disable_breakcheck++;
- // disable job event deferring so the callbacks are processed while waiting.
- if (!disable_job_defer++) {
- // process any pending job events in the deferred queue, but only do this if
- // deferred is not disabled(at the top-level `jobwait()` call)
- loop_process_event(&loop);
- }
// For each item in the input list append an integer to the output list. -3
// is used to represent an invalid job id, -2 is for a interrupted job and
// -1 for jobs that were skipped or timed out.
@@ -11113,8 +11103,6 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv)
// job exits
data->status_ptr = NULL;
}
- disable_job_defer--;
- disable_breakcheck--;
ui_busy_stop();
rv->lv_refcount++;
@@ -21053,6 +21041,7 @@ static inline TerminalJobData *common_job_init(char **argv, ufunc_T *on_stdout,
data->on_stderr = on_stderr;
data->on_exit = on_exit;
data->self = self;
+ data->events = queue_new_child(loop.events);
if (pty) {
data->proc.pty = pty_process_init(&loop, data);
} else {
@@ -21064,6 +21053,7 @@ static inline TerminalJobData *common_job_init(char **argv, ufunc_T *on_stdout,
proc->out = &data->out;
proc->err = &data->err;
proc->cb = on_process_exit;
+ proc->events = data->events;
return data;
}
@@ -21118,7 +21108,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv)
return true;
}
-static inline void free_term_job_data(TerminalJobData *data) {
+static inline void free_term_job_data_event(void **argv)
+{
+ TerminalJobData *data = argv[0];
if (data->on_stdout) {
user_func_unref(data->on_stdout);
}
@@ -21133,17 +21125,25 @@ static inline void free_term_job_data(TerminalJobData *data) {
data->self->internal_refcount--;
dict_unref(data->self);
}
+ queue_free(data->events);
xfree(data);
}
+static inline void free_term_job_data(TerminalJobData *data)
+{
+ // data->queue may still be used after this function returns(process_wait), so
+ // only free in the next event loop iteration
+ queue_put(loop.fast_events, free_term_job_data_event, 1, data);
+}
+
// vimscript job callbacks must be executed on Nvim main loop
-static inline void push_job_event(TerminalJobData *data, ufunc_T *callback,
+static inline void process_job_event(TerminalJobData *data, ufunc_T *callback,
const char *type, char *buf, size_t count, int status)
{
- JobEvent *event_data = xmalloc(sizeof(JobEvent));
- event_data->received = NULL;
+ JobEvent event_data;
+ event_data.received = NULL;
if (buf) {
- event_data->received = list_alloc();
+ event_data.received = list_alloc();
char *ptr = buf;
size_t remaining = count;
size_t off = 0;
@@ -21151,7 +21151,7 @@ static inline void push_job_event(TerminalJobData *data, ufunc_T *callback,
while (off < remaining) {
// append the line
if (ptr[off] == NL) {
- list_append_string(event_data->received, (uint8_t *)ptr, off);
+ list_append_string(event_data.received, (uint8_t *)ptr, off);
size_t skip = off + 1;
ptr += skip;
remaining -= skip;
@@ -21164,17 +21164,14 @@ static inline void push_job_event(TerminalJobData *data, ufunc_T *callback,
}
off++;
}
- list_append_string(event_data->received, (uint8_t *)ptr, off);
+ list_append_string(event_data.received, (uint8_t *)ptr, off);
} else {
- event_data->status = status;
+ event_data.status = status;
}
- event_data->data = data;
- event_data->callback = callback;
- event_data->type = type;
- loop_push_event(&loop, (Event) {
- .handler = on_job_event,
- .data = event_data
- }, !disable_job_defer);
+ event_data.data = data;
+ event_data.callback = callback;
+ event_data.type = type;
+ on_job_event(&event_data);
}
static void on_job_stdout(Stream *stream, RBuffer *buf, void *job, bool eof)
@@ -21198,13 +21195,13 @@ static void on_job_output(Stream *stream, TerminalJobData *data, RBuffer *buf,
RBUFFER_UNTIL_EMPTY(buf, ptr, len) {
// The order here matters, the terminal must receive the data first because
- // push_job_event will modify the read buffer(convert NULs into NLs)
+ // process_job_event will modify the read buffer(convert NULs into NLs)
if (data->term) {
terminal_receive(data->term, ptr, len);
}
if (callback) {
- push_job_event(data, callback, type, ptr, len, 0);
+ process_job_event(data, callback, type, ptr, len, 0);
}
rbuffer_consumed(buf, len);
@@ -21224,7 +21221,7 @@ static void on_process_exit(Process *proc, int status, void *d)
*data->status_ptr = status;
}
- push_job_event(data, data->on_exit, "exit", NULL, 0, status);
+ process_job_event(data, data->on_exit, "exit", NULL, 0, status);
}
static void term_write(char *buf, size_t size, void *d)
@@ -21258,10 +21255,8 @@ static void term_job_data_decref(TerminalJobData *data)
}
}
-static void on_job_event(Event event)
+static void on_job_event(JobEvent *ev)
{
- JobEvent *ev = event.data;
-
if (!ev->callback) {
goto end;
}
@@ -21306,7 +21301,6 @@ end:
pmap_del(uint64_t)(jobs, ev->data->id);
term_job_data_decref(ev->data);
}
- xfree(ev);
}
static TerminalJobData *find_job(uint64_t id)