aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/event/multiqueue.c37
-rw-r--r--src/nvim/msgpack_rpc/channel.c13
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).