aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbfredl <bjorn.linse@gmail.com>2022-05-30 00:59:06 +0200
committerbfredl <bjorn.linse@gmail.com>2022-05-30 14:11:01 +0200
commit1f63052b682a6019d7f092553747272195fbfffd (patch)
treebf1d011b37bc1e61e75c6d8859c830e09d5c0285
parente9803e1de6497ee21f77f45cf2670c2fe4e8ab22 (diff)
downloadrneovim-1f63052b682a6019d7f092553747272195fbfffd.tar.gz
rneovim-1f63052b682a6019d7f092553747272195fbfffd.tar.bz2
rneovim-1f63052b682a6019d7f092553747272195fbfffd.zip
refactor(api): use hashy hash for looking up api method and event names
This avoids generating khash tables at runtime, and is consistent with how evalfuncs lookup work.
-rw-r--r--src/nvim/api/private/dispatch.c33
-rw-r--r--src/nvim/api/private/dispatch.h1
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua35
-rwxr-xr-xsrc/nvim/generators/gen_api_ui_events.lua32
-rw-r--r--src/nvim/main.c1
-rw-r--r--src/nvim/map.c4
-rw-r--r--src/nvim/map.h3
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h1
-rw-r--r--src/nvim/ui_client.c27
-rw-r--r--src/nvim/ui_client.h5
10 files changed, 64 insertions, 78 deletions
diff --git a/src/nvim/api/private/dispatch.c b/src/nvim/api/private/dispatch.c
index ba2e560d63..3da2c2cde4 100644
--- a/src/nvim/api/private/dispatch.c
+++ b/src/nvim/api/private/dispatch.c
@@ -32,37 +32,22 @@
#include "nvim/api/window.h"
#include "nvim/ui_client.h"
-static Map(String, MsgpackRpcRequestHandler) methods = MAP_INIT;
-
-static void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler)
-{
- map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler);
-}
-
-void msgpack_rpc_add_redraw(void)
-{
- msgpack_rpc_add_method_handler(STATIC_CSTR_AS_STRING("redraw"),
- (MsgpackRpcRequestHandler) { .fn = ui_client_handle_redraw,
- .fast = true });
-}
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/private/dispatch_wrappers.generated.h"
+#endif
/// @param name API method name
/// @param name_len name size (includes terminating NUL)
MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, size_t name_len,
Error *error)
{
- String m = { .data = (char *)name, .size = name_len };
- MsgpackRpcRequestHandler rv =
- map_get(String, MsgpackRpcRequestHandler)(&methods, m);
+ int hash = msgpack_rpc_get_handler_for_hash(name, name_len);
- if (!rv.fn) {
+ if (hash < 0) {
api_set_error(error, kErrorTypeException, "Invalid method: %.*s",
- m.size > 0 ? (int)m.size : (int)sizeof("<empty>"),
- m.size > 0 ? m.data : "<empty>");
+ name_len > 0 ? (int)name_len : (int)sizeof("<empty>"),
+ name_len > 0 ? name : "<empty>");
+ return (MsgpackRpcRequestHandler){ 0 };
}
- return rv;
+ return method_handlers[hash];
}
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "api/private/dispatch_wrappers.generated.h"
-#endif
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index bad5a13934..4b7c394944 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -10,6 +10,7 @@ typedef Object (*ApiDispatchWrapper)(uint64_t channel_id,
/// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores
/// functions of this type.
typedef struct {
+ const char *name;
ApiDispatchWrapper fn;
bool fast; // Function is safe to be executed immediately while running the
// uv loop (the loop is run very frequently due to breakcheck).
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index c6dd25154b..38aca32f33 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -16,6 +16,10 @@ local functions = {}
local nvimdir = arg[1]
package.path = nvimdir .. '/?.lua;' .. package.path
+_G.vim = loadfile(nvimdir..'/../../runtime/lua/vim/shared.lua')()
+
+local hashy = require'generators.hashy'
+
-- names of all headers relative to the source root (for inclusion in the
-- generated file)
local headers = {}
@@ -339,24 +343,27 @@ for i = 1, #functions do
end
end
--- Generate a function that initializes method names with handler functions
-output:write([[
-void msgpack_rpc_init_method_table(void)
-{
-]])
-
-for i = 1, #functions do
- local fn = functions[i]
+local remote_fns = {}
+for _,fn in ipairs(functions) do
if fn.remote then
- output:write(' msgpack_rpc_add_method_handler('..
- '(String) {.data = "'..fn.name..'", '..
- '.size = sizeof("'..fn.name..'") - 1}, '..
- '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name)..
- ', .fast = '..tostring(fn.fast)..'});\n')
+ remote_fns[fn.name] = fn
end
end
+remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
+
+local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", vim.tbl_keys(remote_fns), function (idx)
+ return "method_handlers["..idx.."].name"
+end)
+
+output:write("static const MsgpackRpcRequestHandler method_handlers[] = {\n")
+for _, name in ipairs(hashorder) do
+ local fn = remote_fns[name]
+ output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
+ ', .fast = '..tostring(fn.fast)..'},\n')
+end
+output:write("};\n\n")
+output:write(hashfun)
-output:write('\n}\n\n')
output:close()
local mpack_output = io.open(mpack_outputf, 'wb')
diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua
index 5e70442dce..99dfac05e8 100755
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -15,6 +15,9 @@ local client_output = io.open(arg[8], 'wb')
local c_grammar = require('generators.c_grammar')
local events = c_grammar.grammar:match(input:read('*all'))
+_G.vim = loadfile(nvimdir..'/../../runtime/lua/vim/shared.lua')()
+local hashy = require'generators.hashy'
+
local function write_signature(output, ev, prefix, notype)
output:write('('..prefix)
if prefix == "" and #ev.parameters == 0 then
@@ -213,24 +216,25 @@ for i = 1, #events do
end
end
--- Generate the map_init method for client handlers
-client_output:write([[
-void ui_client_methods_table_init(void)
-{
+local client_events = {}
+for _,ev in ipairs(events) do
+ if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) then
+ client_events[ev.name] = ev
+ end
+end
-]])
+local hashorder, hashfun = hashy.hashy_hash("ui_client_handler", vim.tbl_keys(client_events), function (idx)
+ return "event_handlers["..idx.."].name"
+end)
-for i = 1, #events do
- local fn = events[i]
- if (not fn.noexport) and ((not fn.remote_only) or fn.client_impl) then
- client_output:write(' add_ui_client_event_handler('..
- '(String) {.data = "'..fn.name..'", '..
- '.size = sizeof("'..fn.name..'") - 1}, '..
- '(UIClientHandler) ui_client_event_'..fn.name..');\n')
- end
+client_output:write("static const UIClientHandler event_handlers[] = {\n")
+
+for _, name in ipairs(hashorder) do
+ client_output:write(' { .name = "'..name..'", .fn = ui_client_event_'..name..'},\n')
end
-client_output:write('\n}\n\n')
+client_output:write('\n};\n\n')
+client_output:write(hashfun)
proto_output:close()
call_output:close()
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 936b42be23..fabfc57037 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -121,7 +121,6 @@ void event_init(void)
resize_events = multiqueue_new_child(main_loop.events);
// early msgpack-rpc initialization
- msgpack_rpc_init_method_table();
msgpack_rpc_helpers_init();
input_init();
signal_init();
diff --git a/src/nvim/map.c b/src/nvim/map.c
index 05ad113008..d27e40b4ee 100644
--- a/src/nvim/map.c
+++ b/src/nvim/map.c
@@ -14,7 +14,6 @@
#include <stdlib.h>
#include <string.h>
-#include "nvim/api/private/dispatch.h"
#include "nvim/lib/khash.h"
#include "nvim/map.h"
#include "nvim/map_defs.h"
@@ -171,13 +170,10 @@ MAP_IMPL(uint64_t, ssize_t, SSIZE_INITIALIZER)
MAP_IMPL(uint64_t, uint64_t, DEFAULT_INITIALIZER)
MAP_IMPL(uint32_t, uint32_t, DEFAULT_INITIALIZER)
MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER)
-#define MSGPACK_HANDLER_INITIALIZER { .fn = NULL, .fast = false }
-MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
MAP_IMPL(String, handle_T, 0)
MAP_IMPL(String, int, DEFAULT_INITIALIZER)
MAP_IMPL(int, String, DEFAULT_INITIALIZER)
-MAP_IMPL(String, UIClientHandler, NULL)
MAP_IMPL(ColorKey, ColorItem, COLOR_ITEM_INITIALIZER)
diff --git a/src/nvim/map.h b/src/nvim/map.h
index 693ef50127..4f4aaa3552 100644
--- a/src/nvim/map.h
+++ b/src/nvim/map.h
@@ -4,7 +4,6 @@
#include <stdbool.h>
#include "nvim/api/private/defs.h"
-#include "nvim/api/private/dispatch.h"
#include "nvim/extmark_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/map_defs.h"
@@ -44,12 +43,10 @@ MAP_DECLS(uint64_t, uint64_t)
MAP_DECLS(uint32_t, uint32_t)
MAP_DECLS(handle_T, ptr_t)
-MAP_DECLS(String, MsgpackRpcRequestHandler)
MAP_DECLS(HlEntry, int)
MAP_DECLS(String, handle_T)
MAP_DECLS(String, int)
MAP_DECLS(int, String)
-MAP_DECLS(String, UIClientHandler)
MAP_DECLS(ColorKey, ColorItem)
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index 6647779db9..65f1e6b6d6 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -6,6 +6,7 @@
#include <uv.h>
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/event/process.h"
#include "nvim/event/socket.h"
#include "nvim/vim.h"
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index 4d1b9b1c52..be01538f67 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -16,18 +16,17 @@
#include "nvim/ui_client.h"
#include "nvim/vim.h"
-static Map(String, UIClientHandler) ui_client_handlers = MAP_INIT;
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "ui_client.c.generated.h"
+
+# include "ui_events_client.generated.h"
+#endif
// Temporary buffer for converting a single grid_line event
static size_t buf_size = 0;
static schar_T *buf_char = NULL;
static sattr_T *buf_attr = NULL;
-static void add_ui_client_event_handler(String method, UIClientHandler handler)
-{
- map_put(String, UIClientHandler)(&ui_client_handlers, method, handler);
-}
-
void ui_client_init(uint64_t chan)
{
Array args = ARRAY_DICT_INIT;
@@ -44,9 +43,6 @@ void ui_client_init(uint64_t chan)
ADD(args, DICTIONARY_OBJ(opts));
rpc_send_event(chan, "nvim_ui_attach", args);
- msgpack_rpc_add_redraw(); // GAME!
- // TODO(bfredl): use a keyset instead
- ui_client_methods_table_init();
ui_client_channel_id = chan;
}
@@ -61,22 +57,23 @@ void ui_client_init(uint64_t chan)
/// @param channel_id: The id of the rpc channel
/// @param uidata: The dense array containing the ui_events sent by the server
/// @param[out] err Error details, if any
-Object ui_client_handle_redraw(uint64_t channel_id, Array args, Error *error)
+Object handle_ui_client_redraw(uint64_t channel_id, Array args, Error *error)
{
for (size_t i = 0; i < args.size; i++) {
Array call = args.items[i].data.array;
String name = call.items[0].data.string;
- UIClientHandler handler = map_get(String, UIClientHandler)(&ui_client_handlers, name);
- if (!handler) {
+ int hash = ui_client_handler_hash(name.data, name.size);
+ if (hash < 0) {
ELOG("No ui client handler for %s", name.size ? name.data : "<empty>");
continue;
}
+ UIClientHandler handler = event_handlers[hash];
// fprintf(stderr, "%s: %zu\n", name.data, call.size-1);
DLOG("Invoke ui client handler for %s", name.data);
for (size_t j = 1; j < call.size; j++) {
- handler(call.items[j].data.array);
+ handler.fn(call.items[j].data.array);
}
}
@@ -108,10 +105,6 @@ static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb)
return dict2hlattrs(&dict, true, NULL, &err);
}
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "ui_events_client.generated.h"
-#endif
-
void ui_client_event_grid_resize(Array args)
{
if (args.size < 3
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
index d31341ae60..41d9fa6227 100644
--- a/src/nvim/ui_client.h
+++ b/src/nvim/ui_client.h
@@ -3,7 +3,10 @@
#include "nvim/api/private/defs.h"
-typedef void (*UIClientHandler)(Array args);
+typedef struct {
+ const char *name;
+ void (*fn)(Array args);
+} UIClientHandler;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_client.h.generated.h"