Save another GetAtomName round trip Both get_atom_name() and the new atom interner required a round trip. Move get_atom_name() into the atom interner to save one more round trip. This brings xkb_x11_keymap_new_from_device() down to two round trips, which is the minimum possible number. (Also, I think the new code in keymap.c is more readable than the mess I previously created) With this last commit in the series, this definitely: Fixes: https://github.com/xkbcommon/libxkbcommon/pull/217 Signed-off-by: Uli Schlachter <psychon@znc.in>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
diff --git a/src/x11/keymap.c b/src/x11/keymap.c
index 6164d83..1e7fc3b 100644
--- a/src/x11/keymap.c
+++ b/src/x11/keymap.c
@@ -1079,25 +1079,15 @@ get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
reply->which,
&list);
- xcb_get_atom_name_cookie_t cookies[4];
- get_atom_name(conn, list.keycodesName, &cookies[0]);
- get_atom_name(conn, list.symbolsName, &cookies[1]);
- get_atom_name(conn, list.typesName, &cookies[2]);
- get_atom_name(conn, list.compatName, &cookies[3]);
-
- /* We need to ensure all replies are collected and thus no short-circuit */
- bool atom_success = true;
- atom_success &= get_atom_name_reply(conn, list.keycodesName, cookies[0],
- &keymap->keycodes_section_name);
- atom_success &= get_atom_name_reply(conn, list.symbolsName, cookies[1],
- &keymap->symbols_section_name);
- atom_success &= get_atom_name_reply(conn, list.typesName, cookies[2],
- &keymap->types_section_name);
- atom_success &= get_atom_name_reply(conn, list.compatName, cookies[3],
- &keymap->compat_section_name);
-
- if (!atom_success ||
- !get_type_names(keymap, interner, reply, &list) ||
+ x11_atom_interner_get_escaped_atom_name(interner, list.keycodesName,
+ &keymap->keycodes_section_name);
+ x11_atom_interner_get_escaped_atom_name(interner, list.symbolsName,
+ &keymap->symbols_section_name);
+ x11_atom_interner_get_escaped_atom_name(interner, list.typesName,
+ &keymap->types_section_name);
+ x11_atom_interner_get_escaped_atom_name(interner, list.compatName,
+ &keymap->compat_section_name);
+ if (!get_type_names(keymap, interner, reply, &list) ||
!get_indicator_names(keymap, interner, reply, &list) ||
!get_vmod_names(keymap, interner, reply, &list) ||
!get_group_names(keymap, interner, reply, &list) ||
@@ -1105,11 +1095,6 @@ get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
!get_aliases(keymap, conn, reply, &list))
goto fail;
- XkbEscapeMapName(keymap->keycodes_section_name);
- XkbEscapeMapName(keymap->symbols_section_name);
- XkbEscapeMapName(keymap->types_section_name);
- XkbEscapeMapName(keymap->compat_section_name);
-
free(reply);
return true;
diff --git a/src/x11/util.c b/src/x11/util.c
index 6618dfe..ac8f061 100644
--- a/src/x11/util.c
+++ b/src/x11/util.c
@@ -124,48 +124,6 @@ xkb_x11_get_core_keyboard_device_id(xcb_connection_t *conn)
return device_id;
}
-void
-get_atom_name(xcb_connection_t *conn, xcb_atom_t atom,
- xcb_get_atom_name_cookie_t *cookie)
-{
- if (atom == 0) {
- cookie->sequence = 0;
- } else {
- *cookie = xcb_get_atom_name(conn, atom);
- }
-}
-
-bool
-get_atom_name_reply(xcb_connection_t *conn, xcb_atom_t atom,
- xcb_get_atom_name_cookie_t cookie, char **out)
-{
- xcb_get_atom_name_reply_t *reply;
- int length;
- char *name;
-
- if (atom == 0) {
- *out = NULL;
- assert(cookie.sequence == 0);
- return true;
- }
-
- reply = xcb_get_atom_name_reply(conn, cookie, NULL);
- if (!reply)
- return false;
-
- length = xcb_get_atom_name_name_length(reply);
- name = xcb_get_atom_name_name(reply);
-
- *out = strndup(name, length);
- if (!*out) {
- free(reply);
- return false;
- }
-
- free(reply);
- return true;
-}
-
struct x11_atom_cache {
/*
* Invalidate the cache based on the XCB connection.
@@ -204,6 +162,7 @@ x11_atom_interner_init(struct x11_atom_interner *interner,
interner->conn = conn;
interner->num_pending = 0;
interner->num_copies = 0;
+ interner->num_escaped = 0;
}
void
@@ -298,6 +257,48 @@ void x11_atom_interner_round_trip(struct x11_atom_interner *interner) {
}
}
+ for (size_t i = 0; i < interner->num_escaped; i++) {
+ xcb_get_atom_name_reply_t *reply;
+ int length;
+ char *name;
+ char **out = interner->escaped[i].out;
+
+ reply = xcb_get_atom_name_reply(conn, interner->escaped[i].cookie, NULL);
+ *interner->escaped[i].out = NULL;
+ if (!reply) {
+ interner->had_error = true;
+ } else {
+ length = xcb_get_atom_name_name_length(reply);
+ name = xcb_get_atom_name_name(reply);
+
+ *out = strndup(name, length);
+ free(reply);
+ if (*out == NULL) {
+ interner->had_error = true;
+ } else {
+ XkbEscapeMapName(*out);
+ }
+ }
+ }
+
interner->num_pending = 0;
interner->num_copies = 0;
+ interner->num_escaped = 0;
+}
+
+void
+x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner,
+ xcb_atom_t atom, char **out)
+{
+ if (atom == 0) {
+ *out = NULL;
+ return;
+ }
+ size_t idx = interner->num_escaped++;
+ /* There can only be a fixed number of calls to this function "in-flight",
+ * thus we assert this number. Increase the array size if this assert fails.
+ */
+ assert(idx < ARRAY_SIZE(interner->escaped));
+ interner->escaped[idx].out = out;
+ interner->escaped[idx].cookie = xcb_get_atom_name(interner->conn, atom);
}
diff --git a/src/x11/x11-priv.h b/src/x11/x11-priv.h
index 9a6e8e0..480590d 100644
--- a/src/x11/x11-priv.h
+++ b/src/x11/x11-priv.h
@@ -29,16 +29,6 @@
#include "keymap.h"
#include "xkbcommon/xkbcommon-x11.h"
-/* Preparation for get_atom_name_reply() */
-void
-get_atom_name(xcb_connection_t *conn, xcb_atom_t atom,
- xcb_get_atom_name_cookie_t *cookie);
-
-/* Get a strdup'd name of an X atom. */
-bool
-get_atom_name_reply(xcb_connection_t *conn, xcb_atom_t atom,
- xcb_get_atom_name_cookie_t cookie, char **out);
-
struct x11_atom_interner {
struct xkb_context *ctx;
xcb_connection_t *conn;
@@ -56,6 +46,12 @@ struct x11_atom_interner {
xkb_atom_t *out;
} copies[128];
size_t num_copies;
+ /* These are not interned, but saved directly (after XkbEscapeMapName) */
+ struct {
+ xcb_get_atom_name_cookie_t cookie;
+ char **out;
+ } escaped[4];
+ size_t num_escaped;
};
void
@@ -79,4 +75,12 @@ x11_atom_interner_adopt_atoms(struct x11_atom_interner *interner,
const xcb_atom_t *from, xkb_atom_t *to,
size_t count);
+/*
+ * Get a strdup'd and XkbEscapeMapName'd name of an X atom. The actual write is
+ * delayed until the next call to x11_atom_interner_round_trip().
+ */
+void
+x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner,
+ xcb_atom_t atom, char **out);
+
#endif