diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/event/multiqueue.c | 37 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel.c | 13 |
2 files changed, 48 insertions, 2 deletions
diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c index ef9f3f1870..a1b75f66a5 100644 --- a/src/nvim/event/multiqueue.c +++ b/src/nvim/event/multiqueue.c @@ -78,6 +78,13 @@ struct multiqueue { size_t size; }; +typedef struct { + Event event; + bool fired; + int refcount; +} SplitEvent; + + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "event/multiqueue.c.generated.h" #endif @@ -245,3 +252,33 @@ static MultiQueueItem *multiqueue_node_data(QUEUE *q) { return QUEUE_DATA(q, MultiQueueItem, node); } + +/// Allow an event to be processed by multiple child queues to the main queue +/// +/// The handler will be fired once by the _first_ queue that processes the +/// event. Later processing will do nothing (just memory cleanup). +/// +/// @param ev the event +/// @param num number of queues that the split event will be put on +/// @return an Event that is safe to put onto `num` queues +Event event_split(Event ev, int num) +{ + SplitEvent *data = xmalloc(sizeof(*data)); + data->event = ev; + data->fired = false; + data->refcount = num; + return event_create(split_event, 1, data); +} +static void split_event(void ** argv) +{ + SplitEvent *data = argv[0]; + if (!data->fired) { + data->fired = true; + if (data->event.handler) { + data->event.handler(data->event.argv); + } + } + if ((--data->refcount) == 0) { + xfree(data); + } +} diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 81c9f1e3f4..19f626c63b 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -31,6 +31,7 @@ #include "nvim/misc1.h" #include "nvim/lib/kvec.h" #include "nvim/os/input.h" +#include "nvim/ui.h" #if MIN_LOG_LEVEL > DEBUG_LOG_LEVEL #define log_client_msg(...) @@ -355,11 +356,19 @@ static void handle_request(Channel *channel, msgpack_object *request) request_event((void **)&evdata); } } else { - multiqueue_put(channel->events, request_event, 1, evdata); - DLOG("RPC: scheduled %.*s", method->via.bin.size, method->via.bin.ptr); + bool is_resize = handler.fn == handle_nvim_ui_try_resize; + if (is_resize) { + Event ev = event_split(event_create(request_event, 1, evdata), 2); + multiqueue_put_event(channel->events, ev); + multiqueue_put_event(resize_events, ev); + } else { + multiqueue_put(channel->events, request_event, 1, evdata); + DLOG("RPC: scheduled %.*s", method->via.bin.size, method->via.bin.ptr); + } } } + /// Handles a message, depending on the type: /// - Request: invokes method and writes the response (or error). /// - Notification: invokes method (emits `nvim_error_event` on error). |