diff options
author | bfredl <bjorn.linse@gmail.com> | 2022-05-30 00:59:06 +0200 |
---|---|---|
committer | bfredl <bjorn.linse@gmail.com> | 2022-05-30 14:11:01 +0200 |
commit | 1f63052b682a6019d7f092553747272195fbfffd (patch) | |
tree | bf1d011b37bc1e61e75c6d8859c830e09d5c0285 | |
parent | e9803e1de6497ee21f77f45cf2670c2fe4e8ab22 (diff) | |
download | rneovim-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.c | 33 | ||||
-rw-r--r-- | src/nvim/api/private/dispatch.h | 1 | ||||
-rw-r--r-- | src/nvim/generators/gen_api_dispatch.lua | 35 | ||||
-rwxr-xr-x | src/nvim/generators/gen_api_ui_events.lua | 32 | ||||
-rw-r--r-- | src/nvim/main.c | 1 | ||||
-rw-r--r-- | src/nvim/map.c | 4 | ||||
-rw-r--r-- | src/nvim/map.h | 3 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/channel_defs.h | 1 | ||||
-rw-r--r-- | src/nvim/ui_client.c | 27 | ||||
-rw-r--r-- | src/nvim/ui_client.h | 5 |
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" |