Commit b9707c1db094b601ba23f1fcf5e77ec7b53676b7

Uli Schlachter 2021-03-07T08:01:49

Save three more round trips in xkb_x11_keymap_new_from_device() Instead of asking for an atom name and waiting for the reply four times, this now sends four GetAtomName requests and waits for all the replies at once. Thus, this saves three round trips. Signed-off-by: Uli Schlachter <psychon@znc.in>

diff --git a/src/x11/keymap.c b/src/x11/keymap.c
index 38be217..67319a8 100644
--- a/src/x11/keymap.c
+++ b/src/x11/keymap.c
@@ -1087,10 +1087,24 @@ get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
                                         reply->which,
                                         &list);
 
-    if (!get_atom_name(conn, list.keycodesName, &keymap->keycodes_section_name) ||
-        !get_atom_name(conn, list.symbolsName, &keymap->symbols_section_name) ||
-        !get_atom_name(conn, list.typesName, &keymap->types_section_name) ||
-        !get_atom_name(conn, list.compatName, &keymap->compat_section_name) ||
+    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) ||
         !get_indicator_names(keymap, interner, reply, &list) ||
         !get_vmod_names(keymap, interner, reply, &list) ||
diff --git a/src/x11/util.c b/src/x11/util.c
index 766e9a0..6618dfe 100644
--- a/src/x11/util.c
+++ b/src/x11/util.c
@@ -124,20 +124,31 @@ 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(xcb_connection_t *conn, xcb_atom_t atom, char **out)
+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_cookie_t cookie;
     xcb_get_atom_name_reply_t *reply;
     int length;
     char *name;
 
     if (atom == 0) {
         *out = NULL;
+        assert(cookie.sequence == 0);
         return true;
     }
 
-    cookie = xcb_get_atom_name(conn, atom);
     reply = xcb_get_atom_name_reply(conn, cookie, NULL);
     if (!reply)
         return false;
diff --git a/src/x11/x11-priv.h b/src/x11/x11-priv.h
index 5b7f5c2..9a6e8e0 100644
--- a/src/x11/x11-priv.h
+++ b/src/x11/x11-priv.h
@@ -29,9 +29,15 @@
 #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(xcb_connection_t *conn, xcb_atom_t atom, char **out);
+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;