mirror of
				https://github.com/neovim/neovim.git
				synced 2025-11-04 01:34:25 +00:00 
			
		
		
		
	refactor(map): remove extra-allocating map_new/map_free functions
Note: the reason for removing them is not that there after this refactor is no use of them, but rather that having them available is an anti-pattern: they manange an _extra_ heap allocation which has nothing to do with the functionality of the map itself (khash manages the real buffers internally). In case there happens to be a reason to allocate the map structure itself later, this should be made explicit using xcalloc/xfree calls.
This commit is contained in:
		@@ -21,12 +21,12 @@
 | 
			
		||||
#include "nvim/api/window.h"
 | 
			
		||||
#include "nvim/api/deprecated.h"
 | 
			
		||||
 | 
			
		||||
static Map(String, MsgpackRpcRequestHandler) *methods = NULL;
 | 
			
		||||
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);
 | 
			
		||||
  map_put(String, MsgpackRpcRequestHandler)(&methods, method, handler);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// @param name API method name
 | 
			
		||||
@@ -37,7 +37,7 @@ MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name,
 | 
			
		||||
{
 | 
			
		||||
  String m = { .data = (char *)name, .size = name_len };
 | 
			
		||||
  MsgpackRpcRequestHandler rv =
 | 
			
		||||
    map_get(String, MsgpackRpcRequestHandler)(methods, m);
 | 
			
		||||
    map_get(String, MsgpackRpcRequestHandler)(&methods, m);
 | 
			
		||||
 | 
			
		||||
  if (!rv.fn) {
 | 
			
		||||
    api_set_error(error, kErrorTypeException, "Invalid method: %.*s",
 | 
			
		||||
 
 | 
			
		||||
@@ -1724,7 +1724,7 @@ const char *describe_ns(NS ns_id)
 | 
			
		||||
{
 | 
			
		||||
  String name;
 | 
			
		||||
  handle_T id;
 | 
			
		||||
  map_foreach((&namespace_ids), name, id, {
 | 
			
		||||
  map_foreach(&namespace_ids, name, id, {
 | 
			
		||||
    if ((NS)id == ns_id && name.size) {
 | 
			
		||||
      return name.data;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@ void api_vim_free_all_mem(void)
 | 
			
		||||
{
 | 
			
		||||
  String name;
 | 
			
		||||
  handle_T id;
 | 
			
		||||
  map_foreach((&namespace_ids), name, id, {
 | 
			
		||||
  map_foreach(&namespace_ids, name, id, {
 | 
			
		||||
    (void)id;
 | 
			
		||||
    xfree(name.data);
 | 
			
		||||
  })
 | 
			
		||||
@@ -1584,7 +1584,7 @@ Dictionary nvim_get_namespaces(void)
 | 
			
		||||
  String name;
 | 
			
		||||
  handle_T id;
 | 
			
		||||
 | 
			
		||||
  map_foreach((&namespace_ids), name, id, {
 | 
			
		||||
  map_foreach(&namespace_ids, name, id, {
 | 
			
		||||
    PUT(retval, name.data, INTEGER_OBJ(id));
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -32,13 +32,9 @@ static uint64_t next_chan_id = CHAN_STDERR+1;
 | 
			
		||||
/// Teardown the module
 | 
			
		||||
void channel_teardown(void)
 | 
			
		||||
{
 | 
			
		||||
  if (!channels) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  Channel *channel;
 | 
			
		||||
 | 
			
		||||
  map_foreach_value(channels, channel, {
 | 
			
		||||
  map_foreach_value(&channels, channel, {
 | 
			
		||||
    channel_close(channel->id, kChannelPartAll, NULL);
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@@ -152,7 +148,6 @@ bool channel_close(uint64_t id, ChannelPart part, const char **error)
 | 
			
		||||
/// Initializes the module
 | 
			
		||||
void channel_init(void)
 | 
			
		||||
{
 | 
			
		||||
  channels = pmap_new(uint64_t)();
 | 
			
		||||
  channel_alloc(kChannelStreamStderr);
 | 
			
		||||
  rpc_init();
 | 
			
		||||
}
 | 
			
		||||
@@ -177,7 +172,7 @@ Channel *channel_alloc(ChannelStreamType type)
 | 
			
		||||
  chan->exit_status = -1;
 | 
			
		||||
  chan->streamtype = type;
 | 
			
		||||
  assert(chan->id <= VARNUMBER_MAX);
 | 
			
		||||
  pmap_put(uint64_t)(channels, chan->id, chan);
 | 
			
		||||
  pmap_put(uint64_t)(&channels, chan->id, chan);
 | 
			
		||||
  return chan;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -249,7 +244,7 @@ static void free_channel_event(void **argv)
 | 
			
		||||
  callback_reader_free(&chan->on_stderr);
 | 
			
		||||
  callback_free(&chan->on_exit);
 | 
			
		||||
 | 
			
		||||
  pmap_del(uint64_t)(channels, chan->id);
 | 
			
		||||
  pmap_del(uint64_t)(&channels, chan->id);
 | 
			
		||||
  multiqueue_free(chan->events);
 | 
			
		||||
  xfree(chan);
 | 
			
		||||
}
 | 
			
		||||
@@ -259,7 +254,7 @@ static void channel_destroy_early(Channel *chan)
 | 
			
		||||
  if ((chan->id != --next_chan_id)) {
 | 
			
		||||
    abort();
 | 
			
		||||
  }
 | 
			
		||||
  pmap_del(uint64_t)(channels, chan->id);
 | 
			
		||||
  pmap_del(uint64_t)(&channels, chan->id);
 | 
			
		||||
  chan->id = 0;
 | 
			
		||||
 | 
			
		||||
  if ((--chan->refcount != 0)) {
 | 
			
		||||
@@ -899,7 +894,7 @@ Array channel_all_info(void)
 | 
			
		||||
{
 | 
			
		||||
  Channel *channel;
 | 
			
		||||
  Array ret = ARRAY_DICT_INIT;
 | 
			
		||||
  map_foreach_value(channels, channel, {
 | 
			
		||||
  map_foreach_value(&channels, channel, {
 | 
			
		||||
    ADD(ret, DICTIONARY_OBJ(channel_info(channel->id)));
 | 
			
		||||
  });
 | 
			
		||||
  return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -89,7 +89,7 @@ struct Channel {
 | 
			
		||||
  bool callback_scheduled;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
EXTERN PMap(uint64_t) *channels INIT(= NULL);
 | 
			
		||||
EXTERN PMap(uint64_t) channels INIT(= MAP_INIT);
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
# include "channel.h.generated.h"
 | 
			
		||||
@@ -98,7 +98,7 @@ EXTERN PMap(uint64_t) *channels INIT(= NULL);
 | 
			
		||||
/// @returns Channel with the id or NULL if not found
 | 
			
		||||
static inline Channel *find_channel(uint64_t id)
 | 
			
		||||
{
 | 
			
		||||
  return pmap_get(uint64_t)(channels, id);
 | 
			
		||||
  return pmap_get(uint64_t)(&channels, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline Stream *channel_instream(Channel *chan)
 | 
			
		||||
 
 | 
			
		||||
@@ -265,7 +265,7 @@ static partial_T *vvlua_partial;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint64_t last_timer_id = 1;
 | 
			
		||||
static PMap(uint64_t) *timers = NULL;
 | 
			
		||||
static PMap(uint64_t) timers = MAP_INIT;
 | 
			
		||||
 | 
			
		||||
static const char *const msgpack_type_names[] = {
 | 
			
		||||
  [kMPNil] = "nil",
 | 
			
		||||
@@ -326,7 +326,6 @@ void eval_init(void)
 | 
			
		||||
{
 | 
			
		||||
  vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
 | 
			
		||||
 | 
			
		||||
  timers = pmap_new(uint64_t)();
 | 
			
		||||
  struct vimvar   *p;
 | 
			
		||||
 | 
			
		||||
  init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
 | 
			
		||||
@@ -4883,7 +4882,7 @@ bool garbage_collect(bool testing)
 | 
			
		||||
  // Channels
 | 
			
		||||
  {
 | 
			
		||||
    Channel *data;
 | 
			
		||||
    map_foreach_value(channels, data, {
 | 
			
		||||
    map_foreach_value(&channels, data, {
 | 
			
		||||
      set_ref_in_callback_reader(&data->on_data, copyID, NULL, NULL);
 | 
			
		||||
      set_ref_in_callback_reader(&data->on_stderr, copyID, NULL, NULL);
 | 
			
		||||
      set_ref_in_callback(&data->on_exit, copyID, NULL, NULL);
 | 
			
		||||
@@ -4893,7 +4892,7 @@ bool garbage_collect(bool testing)
 | 
			
		||||
  // Timers
 | 
			
		||||
  {
 | 
			
		||||
    timer_T *timer;
 | 
			
		||||
    map_foreach_value(timers, timer, {
 | 
			
		||||
    map_foreach_value(&timers, timer, {
 | 
			
		||||
      set_ref_in_callback(&timer->callback, copyID, NULL, NULL);
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
@@ -7304,7 +7303,7 @@ static bool set_ref_in_callback_reader(CallbackReader *reader, int copyID,
 | 
			
		||||
 | 
			
		||||
timer_T *find_timer_by_nr(varnumber_T xx)
 | 
			
		||||
{
 | 
			
		||||
    return pmap_get(uint64_t)(timers, xx);
 | 
			
		||||
    return pmap_get(uint64_t)(&timers, xx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void add_timer_info(typval_T *rettv, timer_T *timer)
 | 
			
		||||
@@ -7331,9 +7330,9 @@ void add_timer_info(typval_T *rettv, timer_T *timer)
 | 
			
		||||
 | 
			
		||||
void add_timer_info_all(typval_T *rettv)
 | 
			
		||||
{
 | 
			
		||||
  tv_list_alloc_ret(rettv, map_size(timers));
 | 
			
		||||
  tv_list_alloc_ret(rettv, map_size(&timers));
 | 
			
		||||
  timer_T *timer;
 | 
			
		||||
  map_foreach_value(timers, timer, {
 | 
			
		||||
  map_foreach_value(&timers, timer, {
 | 
			
		||||
    if (!timer->stopped) {
 | 
			
		||||
      add_timer_info(rettv, timer);
 | 
			
		||||
    }
 | 
			
		||||
@@ -7413,7 +7412,7 @@ uint64_t timer_start(const long timeout,
 | 
			
		||||
  timer->tw.blockable = true;
 | 
			
		||||
  time_watcher_start(&timer->tw, timer_due_cb, timeout, timeout);
 | 
			
		||||
 | 
			
		||||
  pmap_put(uint64_t)(timers, timer->timer_id, timer);
 | 
			
		||||
  pmap_put(uint64_t)(&timers, timer->timer_id, timer);
 | 
			
		||||
  return timer->timer_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -7435,7 +7434,7 @@ static void timer_close_cb(TimeWatcher *tw, void *data)
 | 
			
		||||
  timer_T *timer = (timer_T *)data;
 | 
			
		||||
  multiqueue_free(timer->tw.events);
 | 
			
		||||
  callback_free(&timer->callback);
 | 
			
		||||
  pmap_del(uint64_t)(timers, timer->timer_id);
 | 
			
		||||
  pmap_del(uint64_t)(&timers, timer->timer_id);
 | 
			
		||||
  timer_decref(timer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -7449,7 +7448,7 @@ static void timer_decref(timer_T *timer)
 | 
			
		||||
void timer_stop_all(void)
 | 
			
		||||
{
 | 
			
		||||
  timer_T *timer;
 | 
			
		||||
  map_foreach_value(timers, timer, {
 | 
			
		||||
  map_foreach_value(&timers, timer, {
 | 
			
		||||
    timer_stop(timer);
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -260,7 +260,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
 | 
			
		||||
  }
 | 
			
		||||
  uint64_t id;
 | 
			
		||||
  ssize_t decor_id;
 | 
			
		||||
  map_foreach((&delete_set), id, decor_id, {
 | 
			
		||||
  map_foreach(&delete_set, id, decor_id, {
 | 
			
		||||
    mtpos_t pos = marktree_lookup(buf->b_marktree, id, itr);
 | 
			
		||||
    assert(itr->node);
 | 
			
		||||
    marktree_del_itr(buf->b_marktree, itr, false);
 | 
			
		||||
 
 | 
			
		||||
@@ -321,8 +321,6 @@ end
 | 
			
		||||
output:write([[
 | 
			
		||||
void msgpack_rpc_init_method_table(void)
 | 
			
		||||
{
 | 
			
		||||
  methods = map_new(String, MsgpackRpcRequestHandler)();
 | 
			
		||||
 | 
			
		||||
]])
 | 
			
		||||
 | 
			
		||||
for i = 1, #functions do
 | 
			
		||||
 
 | 
			
		||||
@@ -68,7 +68,8 @@ typedef struct {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if __has_feature(address_sanitizer)
 | 
			
		||||
  PMap(handle_T) *nlua_ref_markers = NULL;
 | 
			
		||||
  static PMap(handle_T) nlua_ref_markers = MAP_INIT;
 | 
			
		||||
  static bool nlua_track_refs = false;
 | 
			
		||||
# define NLUA_TRACK_REFS
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -568,7 +569,7 @@ void nlua_init(void)
 | 
			
		||||
#ifdef NLUA_TRACK_REFS
 | 
			
		||||
  const char *env = os_getenv("NVIM_LUA_NOTRACK");
 | 
			
		||||
  if (!env || !*env) {
 | 
			
		||||
    nlua_ref_markers = pmap_new(handle_T)();
 | 
			
		||||
    nlua_track_refs = true;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -599,10 +600,10 @@ void nlua_free_all_mem(void)
 | 
			
		||||
    fprintf(stderr, "%d lua references were leaked!", nlua_refcount);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (nlua_ref_markers) {
 | 
			
		||||
  if (nlua_track_refs) {
 | 
			
		||||
    // in case there are leaked luarefs, leak the associated memory
 | 
			
		||||
    // to get LeakSanitizer stacktraces on exit
 | 
			
		||||
    pmap_free(handle_T)(nlua_ref_markers);
 | 
			
		||||
    pmap_destroy(handle_T)(&nlua_ref_markers);
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -1001,9 +1002,9 @@ LuaRef nlua_ref(lua_State *lstate, int index)
 | 
			
		||||
  if (ref > 0) {
 | 
			
		||||
    nlua_refcount++;
 | 
			
		||||
#ifdef NLUA_TRACK_REFS
 | 
			
		||||
  if (nlua_ref_markers) {
 | 
			
		||||
  if (nlua_track_refs) {
 | 
			
		||||
    // dummy allocation to make LeakSanitizer track our luarefs
 | 
			
		||||
    pmap_put(handle_T)(nlua_ref_markers, ref, xmalloc(3));
 | 
			
		||||
    pmap_put(handle_T)(&nlua_ref_markers, ref, xmalloc(3));
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
@@ -1017,8 +1018,8 @@ void nlua_unref(lua_State *lstate, LuaRef ref)
 | 
			
		||||
    nlua_refcount--;
 | 
			
		||||
#ifdef NLUA_TRACK_REFS
 | 
			
		||||
    // NB: don't remove entry from map to track double-unref
 | 
			
		||||
    if (nlua_ref_markers) {
 | 
			
		||||
      xfree(pmap_get(handle_T)(nlua_ref_markers, ref));
 | 
			
		||||
    if (nlua_track_refs) {
 | 
			
		||||
      xfree(pmap_get(handle_T)(&nlua_ref_markers, ref));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    luaL_unref(lstate, LUA_REGISTRYINDEX, ref);
 | 
			
		||||
 
 | 
			
		||||
@@ -101,7 +101,7 @@ static struct luaL_Reg treecursor_meta[] = {
 | 
			
		||||
  { NULL, NULL }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PMap(cstr_t) *langs;
 | 
			
		||||
static PMap(cstr_t) langs = MAP_INIT;
 | 
			
		||||
 | 
			
		||||
static void build_meta(lua_State *L, const char *tname, const luaL_Reg *meta)
 | 
			
		||||
{
 | 
			
		||||
@@ -119,8 +119,6 @@ static void build_meta(lua_State *L, const char *tname, const luaL_Reg *meta)
 | 
			
		||||
/// all global state is stored in the regirstry of the lua_State
 | 
			
		||||
void tslua_init(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
  langs = pmap_new(cstr_t)();
 | 
			
		||||
 | 
			
		||||
  // type metatables
 | 
			
		||||
  build_meta(L, TS_META_PARSER, parser_meta);
 | 
			
		||||
  build_meta(L, TS_META_TREE, tree_meta);
 | 
			
		||||
@@ -133,7 +131,7 @@ void tslua_init(lua_State *L)
 | 
			
		||||
int tslua_has_language(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
  const char *lang_name = luaL_checkstring(L, 1);
 | 
			
		||||
  lua_pushboolean(L, pmap_has(cstr_t)(langs, lang_name));
 | 
			
		||||
  lua_pushboolean(L, pmap_has(cstr_t)(&langs, lang_name));
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -142,7 +140,7 @@ int tslua_add_language(lua_State *L)
 | 
			
		||||
  const char *path = luaL_checkstring(L, 1);
 | 
			
		||||
  const char *lang_name = luaL_checkstring(L, 2);
 | 
			
		||||
 | 
			
		||||
  if (pmap_has(cstr_t)(langs, lang_name)) {
 | 
			
		||||
  if (pmap_has(cstr_t)(&langs, lang_name)) {
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -185,7 +183,7 @@ int tslua_add_language(lua_State *L)
 | 
			
		||||
        TREE_SITTER_LANGUAGE_VERSION, lang_version);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pmap_put(cstr_t)(langs, xstrdup(lang_name), lang);
 | 
			
		||||
  pmap_put(cstr_t)(&langs, xstrdup(lang_name), lang);
 | 
			
		||||
 | 
			
		||||
  lua_pushboolean(L, true);
 | 
			
		||||
  return 1;
 | 
			
		||||
@@ -195,7 +193,7 @@ int tslua_inspect_lang(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
  const char *lang_name = luaL_checkstring(L, 1);
 | 
			
		||||
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
 | 
			
		||||
  if (!lang) {
 | 
			
		||||
    return luaL_error(L, "no such language: %s", lang_name);
 | 
			
		||||
  }
 | 
			
		||||
@@ -243,7 +241,7 @@ int tslua_push_parser(lua_State *L)
 | 
			
		||||
  // Gather language name
 | 
			
		||||
  const char *lang_name = luaL_checkstring(L, 1);
 | 
			
		||||
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
 | 
			
		||||
  if (!lang) {
 | 
			
		||||
    return luaL_error(L, "no such language: %s", lang_name);
 | 
			
		||||
  }
 | 
			
		||||
@@ -1127,7 +1125,7 @@ int tslua_parse_query(lua_State *L)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const char *lang_name = lua_tostring(L, 1);
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(langs, lang_name);
 | 
			
		||||
  TSLanguage *lang = pmap_get(cstr_t)(&langs, lang_name);
 | 
			
		||||
  if (!lang) {
 | 
			
		||||
    return luaL_error(L, "no such language: %s", lang_name);
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -54,19 +54,6 @@
 | 
			
		||||
  INITIALIZER_DECLARE(T, U, __VA_ARGS__); \
 | 
			
		||||
  __KHASH_IMPL(T##_##U##_map,, T, U, 1, T##_hash, T##_eq) \
 | 
			
		||||
  \
 | 
			
		||||
  Map(T, U) *map_##T##_##U##_new() \
 | 
			
		||||
  { \
 | 
			
		||||
    Map(T, U) *rv = xcalloc(1, sizeof(Map(T, U))); \
 | 
			
		||||
    /* khash_t table member is zero-initialized */ \
 | 
			
		||||
    return rv; \
 | 
			
		||||
  } \
 | 
			
		||||
  \
 | 
			
		||||
  void map_##T##_##U##_free(Map(T, U) *map) \
 | 
			
		||||
  { \
 | 
			
		||||
    kh_dealloc(T##_##U##_map, &map->table); \
 | 
			
		||||
    xfree(map); \
 | 
			
		||||
  } \
 | 
			
		||||
  \
 | 
			
		||||
  void map_##T##_##U##_destroy(Map(T, U) *map) \
 | 
			
		||||
  { \
 | 
			
		||||
    kh_dealloc(T##_##U##_map, &map->table); \
 | 
			
		||||
 
 | 
			
		||||
@@ -62,8 +62,6 @@ MAP_DECLS(ColorKey, ColorItem)
 | 
			
		||||
#define MAP_INIT { { 0, 0, 0, 0, NULL, NULL, NULL } }
 | 
			
		||||
#define map_init(k, v, map) do { *(map) = (Map(k, v))MAP_INIT; } while (false)
 | 
			
		||||
 | 
			
		||||
#define map_new(T, U) map_##T##_##U##_new
 | 
			
		||||
#define map_free(T, U) map_##T##_##U##_free
 | 
			
		||||
#define map_destroy(T, U) map_##T##_##U##_destroy
 | 
			
		||||
#define map_get(T, U) map_##T##_##U##_get
 | 
			
		||||
#define map_has(T, U) map_##T##_##U##_has
 | 
			
		||||
@@ -75,8 +73,6 @@ MAP_DECLS(ColorKey, ColorItem)
 | 
			
		||||
 | 
			
		||||
#define map_size(map) ((map)->table.size)
 | 
			
		||||
 | 
			
		||||
#define pmap_new(T) map_new(T, ptr_t)
 | 
			
		||||
#define pmap_free(T) map_free(T, ptr_t)
 | 
			
		||||
#define pmap_destroy(T) map_destroy(T, ptr_t)
 | 
			
		||||
#define pmap_get(T) map_get(T, ptr_t)
 | 
			
		||||
#define pmap_has(T) map_has(T, ptr_t)
 | 
			
		||||
@@ -89,10 +85,10 @@ MAP_DECLS(ColorKey, ColorItem)
 | 
			
		||||
#define pmap_init(k, map) map_init(k, ptr_t, map)
 | 
			
		||||
 | 
			
		||||
#define map_foreach(map, key, value, block) \
 | 
			
		||||
  kh_foreach(&map->table, key, value, block)
 | 
			
		||||
  kh_foreach(&(map)->table, key, value, block)
 | 
			
		||||
 | 
			
		||||
#define map_foreach_value(map, value, block) \
 | 
			
		||||
  kh_foreach_value(&map->table, value, block)
 | 
			
		||||
  kh_foreach_value(&(map)->table, value, block)
 | 
			
		||||
 | 
			
		||||
void pmap_del2(PMap(cstr_t) *map, const char *key);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
#define log_server_msg(...)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static PMap(cstr_t) *event_strings = NULL;
 | 
			
		||||
static PMap(cstr_t) event_strings = MAP_INIT;
 | 
			
		||||
static msgpack_sbuffer out_buffer;
 | 
			
		||||
 | 
			
		||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
 | 
			
		||||
@@ -48,7 +48,6 @@ static msgpack_sbuffer out_buffer;
 | 
			
		||||
void rpc_init(void)
 | 
			
		||||
{
 | 
			
		||||
  ch_before_blocking_events = multiqueue_new_child(main_loop.events);
 | 
			
		||||
  event_strings = pmap_new(cstr_t)();
 | 
			
		||||
  msgpack_sbuffer_init(&out_buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -60,7 +59,6 @@ void rpc_start(Channel *channel)
 | 
			
		||||
  RpcState *rpc = &channel->rpc;
 | 
			
		||||
  rpc->closed = false;
 | 
			
		||||
  rpc->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE);
 | 
			
		||||
  rpc->subscribed_events = pmap_new(cstr_t)();
 | 
			
		||||
  rpc->next_request_id = 1;
 | 
			
		||||
  rpc->info = (Dictionary)ARRAY_DICT_INIT;
 | 
			
		||||
  kv_init(rpc->call_stack);
 | 
			
		||||
@@ -183,11 +181,11 @@ void rpc_subscribe(uint64_t id, char *event)
 | 
			
		||||
    abort();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char *event_string = pmap_get(cstr_t)(event_strings, event);
 | 
			
		||||
  char *event_string = pmap_get(cstr_t)(&event_strings, event);
 | 
			
		||||
 | 
			
		||||
  if (!event_string) {
 | 
			
		||||
    event_string = xstrdup(event);
 | 
			
		||||
    pmap_put(cstr_t)(event_strings, event_string, event_string);
 | 
			
		||||
    pmap_put(cstr_t)(&event_strings, event_string, event_string);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pmap_put(cstr_t)(channel->rpc.subscribed_events, event_string, event_string);
 | 
			
		||||
@@ -497,7 +495,7 @@ static void broadcast_event(const char *name, Array args)
 | 
			
		||||
  kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
 | 
			
		||||
  Channel *channel;
 | 
			
		||||
 | 
			
		||||
  map_foreach_value(channels, channel, {
 | 
			
		||||
  map_foreach_value(&channels, channel, {
 | 
			
		||||
    if (channel->is_rpc
 | 
			
		||||
        && pmap_has(cstr_t)(channel->rpc.subscribed_events, name)) {
 | 
			
		||||
      kv_push(subscribed, channel);
 | 
			
		||||
@@ -528,7 +526,7 @@ end:
 | 
			
		||||
 | 
			
		||||
static void unsubscribe(Channel *channel, char *event)
 | 
			
		||||
{
 | 
			
		||||
  char *event_string = pmap_get(cstr_t)(event_strings, event);
 | 
			
		||||
  char *event_string = pmap_get(cstr_t)(&event_strings, event);
 | 
			
		||||
  if (!event_string) {
 | 
			
		||||
      WLOG("RPC: ch %" PRIu64 ": tried to unsubscribe unknown event '%s'",
 | 
			
		||||
           channel->id, event);
 | 
			
		||||
@@ -536,7 +534,7 @@ static void unsubscribe(Channel *channel, char *event)
 | 
			
		||||
  }
 | 
			
		||||
  pmap_del(cstr_t)(channel->rpc.subscribed_events, event_string);
 | 
			
		||||
 | 
			
		||||
  map_foreach_value(channels, channel, {
 | 
			
		||||
  map_foreach_value(&channels, channel, {
 | 
			
		||||
    if (channel->is_rpc
 | 
			
		||||
        && pmap_has(cstr_t)(channel->rpc.subscribed_events, event_string)) {
 | 
			
		||||
      return;
 | 
			
		||||
@@ -544,7 +542,7 @@ static void unsubscribe(Channel *channel, char *event)
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // Since the string is no longer used by other channels, release it's memory
 | 
			
		||||
  pmap_del(cstr_t)(event_strings, event_string);
 | 
			
		||||
  pmap_del(cstr_t)(&event_strings, event_string);
 | 
			
		||||
  xfree(event_string);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -583,7 +581,7 @@ void rpc_free(Channel *channel)
 | 
			
		||||
    unsubscribe(channel, event_string);
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  pmap_free(cstr_t)(channel->rpc.subscribed_events);
 | 
			
		||||
  pmap_destroy(cstr_t)(channel->rpc.subscribed_events);
 | 
			
		||||
  kv_destroy(channel->rpc.call_stack);
 | 
			
		||||
  api_free_dictionary(channel->rpc.info);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@ typedef struct {
 | 
			
		||||
} RequestEvent;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  PMap(cstr_t) *subscribed_events;
 | 
			
		||||
  PMap(cstr_t) subscribed_events[1];
 | 
			
		||||
  bool closed;
 | 
			
		||||
  msgpack_unpacker *unpacker;
 | 
			
		||||
  uint32_t next_request_id;
 | 
			
		||||
 
 | 
			
		||||
@@ -35,12 +35,11 @@
 | 
			
		||||
 | 
			
		||||
// Because `uv_os_getenv` requires allocating, we must manage a map to maintain
 | 
			
		||||
// the behavior of `os_getenv`.
 | 
			
		||||
static PMap(cstr_t) *envmap;
 | 
			
		||||
static PMap(cstr_t) envmap = MAP_INIT;
 | 
			
		||||
static uv_mutex_t mutex;
 | 
			
		||||
 | 
			
		||||
void env_init(void)
 | 
			
		||||
{
 | 
			
		||||
  envmap = pmap_new(cstr_t)();
 | 
			
		||||
  uv_mutex_init(&mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -66,8 +65,8 @@ const char *os_getenv(const char *name)
 | 
			
		||||
  }
 | 
			
		||||
  uv_mutex_lock(&mutex);
 | 
			
		||||
  int r = 0;
 | 
			
		||||
  if (pmap_has(cstr_t)(envmap, name)
 | 
			
		||||
      && !!(e = (char *)pmap_get(cstr_t)(envmap, name))) {
 | 
			
		||||
  if (pmap_has(cstr_t)(&envmap, name)
 | 
			
		||||
      && !!(e = (char *)pmap_get(cstr_t)(&envmap, name))) {
 | 
			
		||||
    if (e[0] != '\0') {
 | 
			
		||||
      // Found non-empty cached env var.
 | 
			
		||||
      // NOTE: This risks incoherence if an in-process library changes the
 | 
			
		||||
@@ -75,7 +74,7 @@ const char *os_getenv(const char *name)
 | 
			
		||||
      //       that turns out to be a problem, we can just remove this codepath.
 | 
			
		||||
      goto end;
 | 
			
		||||
    }
 | 
			
		||||
    pmap_del2(envmap, name);
 | 
			
		||||
    pmap_del2(&envmap, name);
 | 
			
		||||
  }
 | 
			
		||||
  e = xmalloc(size);
 | 
			
		||||
  r = uv_os_getenv(name, e, &size);
 | 
			
		||||
@@ -88,7 +87,7 @@ const char *os_getenv(const char *name)
 | 
			
		||||
    e = NULL;
 | 
			
		||||
    goto end;
 | 
			
		||||
  }
 | 
			
		||||
  pmap_put(cstr_t)(envmap, xstrdup(name), e);
 | 
			
		||||
  pmap_put(cstr_t)(&envmap, xstrdup(name), e);
 | 
			
		||||
end:
 | 
			
		||||
  // Must do this before ELOG, log.c may call os_setenv.
 | 
			
		||||
  uv_mutex_unlock(&mutex);
 | 
			
		||||
@@ -157,7 +156,7 @@ int os_setenv(const char *name, const char *value, int overwrite)
 | 
			
		||||
  assert(r != UV_EINVAL);
 | 
			
		||||
  // Destroy the old map item. Do this AFTER uv_os_setenv(), because `value`
 | 
			
		||||
  // could be a previous os_getenv() result.
 | 
			
		||||
  pmap_del2(envmap, name);
 | 
			
		||||
  pmap_del2(&envmap, name);
 | 
			
		||||
  // Must do this before ELOG, log.c may call os_setenv.
 | 
			
		||||
  uv_mutex_unlock(&mutex);
 | 
			
		||||
  if (r != 0) {
 | 
			
		||||
@@ -174,7 +173,7 @@ int os_unsetenv(const char *name)
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
  uv_mutex_lock(&mutex);
 | 
			
		||||
  pmap_del2(envmap, name);
 | 
			
		||||
  pmap_del2(&envmap, name);
 | 
			
		||||
  int r = uv_os_unsetenv(name);
 | 
			
		||||
  // Must do this before ELOG, log.c may call os_setenv.
 | 
			
		||||
  uv_mutex_unlock(&mutex);
 | 
			
		||||
 
 | 
			
		||||
@@ -152,11 +152,10 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
 | 
			
		||||
  .sb_popline  = term_sb_pop,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PMap(ptr_t) *invalidated_terminals;
 | 
			
		||||
static PMap(ptr_t) invalidated_terminals = MAP_INIT;
 | 
			
		||||
 | 
			
		||||
void terminal_init(void)
 | 
			
		||||
{
 | 
			
		||||
  invalidated_terminals = pmap_new(ptr_t)();
 | 
			
		||||
  time_watcher_init(&main_loop, &refresh_timer, NULL);
 | 
			
		||||
  // refresh_timer_cb will redraw the screen which can call vimscript
 | 
			
		||||
  refresh_timer.events = multiqueue_new_child(main_loop.events);
 | 
			
		||||
@@ -167,8 +166,10 @@ void terminal_teardown(void)
 | 
			
		||||
  time_watcher_stop(&refresh_timer);
 | 
			
		||||
  multiqueue_free(refresh_timer.events);
 | 
			
		||||
  time_watcher_close(&refresh_timer, NULL);
 | 
			
		||||
  pmap_free(ptr_t)(invalidated_terminals);
 | 
			
		||||
  invalidated_terminals = NULL;
 | 
			
		||||
  pmap_destroy(ptr_t)(&invalidated_terminals);
 | 
			
		||||
  // terminal_destroy might be called after terminal_teardown is invoked
 | 
			
		||||
  // make sure it is in an empty, valid state
 | 
			
		||||
  pmap_init(ptr_t, &invalidated_terminals);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// public API {{{
 | 
			
		||||
@@ -525,14 +526,12 @@ void terminal_destroy(Terminal *term)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!term->refcount) {
 | 
			
		||||
    // might be destroyed after terminal_teardown is invoked
 | 
			
		||||
    if (invalidated_terminals
 | 
			
		||||
        && pmap_has(ptr_t)(invalidated_terminals, term)) {
 | 
			
		||||
    if (pmap_has(ptr_t)(&invalidated_terminals, term)) {
 | 
			
		||||
      // flush any pending changes to the buffer
 | 
			
		||||
      block_autocmds();
 | 
			
		||||
      refresh_terminal(term);
 | 
			
		||||
      unblock_autocmds();
 | 
			
		||||
      pmap_del(ptr_t)(invalidated_terminals, term);
 | 
			
		||||
      pmap_del(ptr_t)(&invalidated_terminals, term);
 | 
			
		||||
    }
 | 
			
		||||
    for (size_t i = 0; i < term->sb_current; i++) {
 | 
			
		||||
      xfree(term->sb_buffer[i]);
 | 
			
		||||
@@ -869,7 +868,7 @@ static int term_sb_push(int cols, const VTermScreenCell *cells, void *data)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  memcpy(sbrow->cells, cells, sizeof(cells[0]) * c);
 | 
			
		||||
  pmap_put(ptr_t)(invalidated_terminals, term, NULL);
 | 
			
		||||
  pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
 | 
			
		||||
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -910,7 +909,7 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  xfree(sbrow);
 | 
			
		||||
  pmap_put(ptr_t)(invalidated_terminals, term, NULL);
 | 
			
		||||
  pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
 | 
			
		||||
 | 
			
		||||
  return 1;
 | 
			
		||||
}
 | 
			
		||||
@@ -1212,7 +1211,7 @@ static void invalidate_terminal(Terminal *term, int start_row, int end_row)
 | 
			
		||||
    term->invalid_end = MAX(term->invalid_end, end_row);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  pmap_put(ptr_t)(invalidated_terminals, term, NULL);
 | 
			
		||||
  pmap_put(ptr_t)(&invalidated_terminals, term, NULL);
 | 
			
		||||
  if (!refresh_pending) {
 | 
			
		||||
    time_watcher_start(&refresh_timer, refresh_timer_cb, REFRESH_DELAY, 0);
 | 
			
		||||
    refresh_pending = true;
 | 
			
		||||
@@ -1254,10 +1253,10 @@ static void refresh_timer_cb(TimeWatcher *watcher, void *data)
 | 
			
		||||
  void *stub; (void)(stub);
 | 
			
		||||
  // don't process autocommands while updating terminal buffers
 | 
			
		||||
  block_autocmds();
 | 
			
		||||
  map_foreach(invalidated_terminals, term, stub, {
 | 
			
		||||
  map_foreach(&invalidated_terminals, term, stub, {
 | 
			
		||||
    refresh_terminal(term);
 | 
			
		||||
  });
 | 
			
		||||
  pmap_clear(ptr_t)(invalidated_terminals);
 | 
			
		||||
  pmap_clear(ptr_t)(&invalidated_terminals);
 | 
			
		||||
  unblock_autocmds();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user