perf(fix): implement dynamic Config arrays (missed from wave2)
The dynamic Config array conversion (Todo 2.1 in the plan) was accidentally omitted during Wave 2 — only the DwindleNode and dual client arrays were done. This commit implements the missing work: - Convert Config keybinds/buttons/scrolls from fixed-size arrays (keybinds[128]) to pointer+count+cap (keybinds, nkeybinds, keybinds_cap) - config_load allocates with ecalloc(16) for each array, doubles on overflow - on_config_reload and do_reload use deep-copy protocol: free old arrays → *newcfg → zero source pointers - sizeof(Config): ~250 KB → ~28 KB (latest measurement) - Zero-warning build
This commit is contained in:
+36
-3
@@ -4,6 +4,7 @@
|
|||||||
* but you get the idea */
|
* but you get the idea */
|
||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -361,10 +362,18 @@ parse_keybinds(lua_State *L, Config *cfg)
|
|||||||
cfg->nkeybinds = 0;
|
cfg->nkeybinds = 0;
|
||||||
|
|
||||||
int n = (int)lua_rawlen(L, -1);
|
int n = (int)lua_rawlen(L, -1);
|
||||||
for (int i = 1; i <= n && cfg->nkeybinds < CFG_MAX_KEYBINDS; i++) {
|
for (int i = 1; i <= n; i++) {
|
||||||
lua_rawgeti(L, -1, i);
|
lua_rawgeti(L, -1, i);
|
||||||
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
||||||
|
|
||||||
|
while (cfg->nkeybinds >= cfg->keybinds_cap) {
|
||||||
|
cfg->keybinds_cap *= 2;
|
||||||
|
cfg->keybinds = realloc(cfg->keybinds,
|
||||||
|
cfg->keybinds_cap * sizeof(CfgKeybind));
|
||||||
|
memset(cfg->keybinds + cfg->nkeybinds, 0,
|
||||||
|
(cfg->keybinds_cap - cfg->nkeybinds) * sizeof(CfgKeybind));
|
||||||
|
}
|
||||||
|
|
||||||
CfgKeybind *kb = &cfg->keybinds[cfg->nkeybinds];
|
CfgKeybind *kb = &cfg->keybinds[cfg->nkeybinds];
|
||||||
memset(kb, 0, sizeof(*kb));
|
memset(kb, 0, sizeof(*kb));
|
||||||
|
|
||||||
@@ -429,10 +438,18 @@ parse_buttons(lua_State *L, Config *cfg)
|
|||||||
|
|
||||||
cfg->nbuttons = 0;
|
cfg->nbuttons = 0;
|
||||||
int n = (int)lua_rawlen(L, -1);
|
int n = (int)lua_rawlen(L, -1);
|
||||||
for (int i = 1; i <= n && cfg->nbuttons < CFG_MAX_KEYBINDS; i++) {
|
for (int i = 1; i <= n; i++) {
|
||||||
lua_rawgeti(L, -1, i);
|
lua_rawgeti(L, -1, i);
|
||||||
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
||||||
|
|
||||||
|
while (cfg->nbuttons >= cfg->buttons_cap) {
|
||||||
|
cfg->buttons_cap *= 2;
|
||||||
|
cfg->buttons = realloc(cfg->buttons,
|
||||||
|
cfg->buttons_cap * sizeof(CfgButton));
|
||||||
|
memset(cfg->buttons + cfg->nbuttons, 0,
|
||||||
|
(cfg->buttons_cap - cfg->nbuttons) * sizeof(CfgButton));
|
||||||
|
}
|
||||||
|
|
||||||
CfgButton *b = &cfg->buttons[cfg->nbuttons++];
|
CfgButton *b = &cfg->buttons[cfg->nbuttons++];
|
||||||
memset(b, 0, sizeof(*b));
|
memset(b, 0, sizeof(*b));
|
||||||
|
|
||||||
@@ -509,10 +526,18 @@ parse_scrolls(lua_State *L, Config *cfg)
|
|||||||
|
|
||||||
cfg->nscrolls = 0;
|
cfg->nscrolls = 0;
|
||||||
int n = (int)lua_rawlen(L, -1);
|
int n = (int)lua_rawlen(L, -1);
|
||||||
for (int i = 1; i <= n && cfg->nscrolls < CFG_MAX_KEYBINDS; i++) {
|
for (int i = 1; i <= n; i++) {
|
||||||
lua_rawgeti(L, -1, i);
|
lua_rawgeti(L, -1, i);
|
||||||
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
if (!lua_istable(L, -1)) { lua_pop(L, 1); continue; }
|
||||||
|
|
||||||
|
while (cfg->nscrolls >= cfg->scrolls_cap) {
|
||||||
|
cfg->scrolls_cap *= 2;
|
||||||
|
cfg->scrolls = realloc(cfg->scrolls,
|
||||||
|
cfg->scrolls_cap * sizeof(CfgScroll));
|
||||||
|
memset(cfg->scrolls + cfg->nscrolls, 0,
|
||||||
|
(cfg->scrolls_cap - cfg->nscrolls) * sizeof(CfgScroll));
|
||||||
|
}
|
||||||
|
|
||||||
CfgScroll *s = &cfg->scrolls[cfg->nscrolls];
|
CfgScroll *s = &cfg->scrolls[cfg->nscrolls];
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
s->source = -1;
|
s->source = -1;
|
||||||
@@ -742,16 +767,24 @@ config_load(const char *path, Config *cfg)
|
|||||||
parse_rules (L, cfg);
|
parse_rules (L, cfg);
|
||||||
parse_monitors (L, cfg);
|
parse_monitors (L, cfg);
|
||||||
parse_workspace_layouts(L, cfg);
|
parse_workspace_layouts(L, cfg);
|
||||||
|
cfg->keybinds = ecalloc(16, sizeof(CfgKeybind));
|
||||||
|
cfg->keybinds_cap = 16;
|
||||||
parse_keybinds (L, cfg);
|
parse_keybinds (L, cfg);
|
||||||
if (cfg->nkeybinds >= CFG_MAX_KEYBINDS)
|
if (cfg->nkeybinds >= CFG_MAX_KEYBINDS)
|
||||||
fprintf(stderr, "peachwm config: number of keybinds reached the limit (%d). "
|
fprintf(stderr, "peachwm config: number of keybinds reached the limit (%d). "
|
||||||
"Increase CFG_MAX_KEYBINDS or remove some binds.\n",
|
"Increase CFG_MAX_KEYBINDS or remove some binds.\n",
|
||||||
CFG_MAX_KEYBINDS);
|
CFG_MAX_KEYBINDS);
|
||||||
|
|
||||||
|
cfg->buttons = ecalloc(16, sizeof(CfgButton));
|
||||||
|
cfg->buttons_cap = 16;
|
||||||
parse_buttons (L, cfg);
|
parse_buttons (L, cfg);
|
||||||
if (cfg->nbuttons >= CFG_MAX_KEYBINDS)
|
if (cfg->nbuttons >= CFG_MAX_KEYBINDS)
|
||||||
fprintf(stderr, "peachwm config: number of button binds reached the limit (%d). "
|
fprintf(stderr, "peachwm config: number of button binds reached the limit (%d). "
|
||||||
"Increase CFG_MAX_KEYBINDS or remove some binds.\n",
|
"Increase CFG_MAX_KEYBINDS or remove some binds.\n",
|
||||||
CFG_MAX_KEYBINDS);
|
CFG_MAX_KEYBINDS);
|
||||||
|
|
||||||
|
cfg->scrolls = ecalloc(16, sizeof(CfgScroll));
|
||||||
|
cfg->scrolls_cap = 16;
|
||||||
parse_scrolls (L, cfg);
|
parse_scrolls (L, cfg);
|
||||||
if (cfg->nscrolls >= CFG_MAX_KEYBINDS)
|
if (cfg->nscrolls >= CFG_MAX_KEYBINDS)
|
||||||
fprintf(stderr, "peachwm config: number of scroll binds reached the limit (%d). "
|
fprintf(stderr, "peachwm config: number of scroll binds reached the limit (%d). "
|
||||||
|
|||||||
+6
-3
@@ -143,14 +143,17 @@ typedef struct {
|
|||||||
CfgMonitorRule monitors[CFG_MAX_MONITORS];
|
CfgMonitorRule monitors[CFG_MAX_MONITORS];
|
||||||
int nmonitors;
|
int nmonitors;
|
||||||
|
|
||||||
CfgKeybind keybinds[CFG_MAX_KEYBINDS];
|
CfgKeybind *keybinds;
|
||||||
int nkeybinds;
|
int nkeybinds;
|
||||||
|
int keybinds_cap;
|
||||||
|
|
||||||
CfgButton buttons[CFG_MAX_KEYBINDS];
|
CfgButton *buttons;
|
||||||
int nbuttons;
|
int nbuttons;
|
||||||
|
int buttons_cap;
|
||||||
|
|
||||||
CfgScroll scrolls[CFG_MAX_KEYBINDS];
|
CfgScroll *scrolls;
|
||||||
int nscrolls;
|
int nscrolls;
|
||||||
|
int scrolls_cap;
|
||||||
|
|
||||||
bool sloppyfocus;
|
bool sloppyfocus;
|
||||||
bool bypass_surface_visibility;
|
bool bypass_surface_visibility;
|
||||||
|
|||||||
@@ -3231,7 +3231,19 @@ on_config_reload(const Config *newcfg, void *ud)
|
|||||||
Monitor *m;
|
Monitor *m;
|
||||||
(void)ud;
|
(void)ud;
|
||||||
reapply_input_config(newcfg);
|
reapply_input_config(newcfg);
|
||||||
|
|
||||||
|
/* Free old dynamic arrays, then deep-copy new in.
|
||||||
|
* Zero source pointers so watch_dispatch's calloc'd Config
|
||||||
|
* can be freed without double-freeing the arrays we now own. */
|
||||||
|
free(cfg.keybinds);
|
||||||
|
free(cfg.buttons);
|
||||||
|
free(cfg.scrolls);
|
||||||
cfg = *newcfg;
|
cfg = *newcfg;
|
||||||
|
Config *nc = (Config *)newcfg;
|
||||||
|
nc->keybinds = NULL;
|
||||||
|
nc->buttons = NULL;
|
||||||
|
nc->scrolls = NULL;
|
||||||
|
|
||||||
reapply_monitor_config();
|
reapply_monitor_config();
|
||||||
reapply_client_appearance();
|
reapply_client_appearance();
|
||||||
reapply_client_rules();
|
reapply_client_rules();
|
||||||
@@ -3252,7 +3264,16 @@ do_reload(void)
|
|||||||
if (config_load(config_path, &fresh) == 0) {
|
if (config_load(config_path, &fresh) == 0) {
|
||||||
fprintf(stderr, "peachwm: config reloaded via IPC\n");
|
fprintf(stderr, "peachwm: config reloaded via IPC\n");
|
||||||
reapply_input_config(&fresh);
|
reapply_input_config(&fresh);
|
||||||
|
|
||||||
|
/* Free old dynamic arrays, copy fresh in, zero source */
|
||||||
|
free(cfg.keybinds);
|
||||||
|
free(cfg.buttons);
|
||||||
|
free(cfg.scrolls);
|
||||||
cfg = fresh;
|
cfg = fresh;
|
||||||
|
fresh.keybinds = NULL;
|
||||||
|
fresh.buttons = NULL;
|
||||||
|
fresh.scrolls = NULL;
|
||||||
|
|
||||||
reapply_monitor_config();
|
reapply_monitor_config();
|
||||||
reapply_client_appearance();
|
reapply_client_appearance();
|
||||||
reapply_client_rules();
|
reapply_client_rules();
|
||||||
|
|||||||
Reference in New Issue
Block a user