X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fx11%2Futil.c;h=660d8857fb89fed786a168de8237eb489c44fdf9;hb=1bd3b3c7cb52ae77667d45cb46e8b5af3046a8d7;hp=3959a5aa9b4f6330c9894d32102e83a720fc7a28;hpb=f41e609bbea8447fc82849a1a6ea0d116189f2f8;p=platform%2Fupstream%2Flibxkbcommon.git diff --git a/src/x11/util.c b/src/x11/util.c index 3959a5a..660d885 100644 --- a/src/x11/util.c +++ b/src/x11/util.c @@ -155,6 +155,20 @@ get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out) return true; } +struct x11_atom_cache { + /* + * Invalidate the cache based on the XCB connection. + * X11 atoms are actually not per connection or client, but per X server + * session. But better be safe just in case we survive an X server restart. + */ + xcb_connection_t *conn; + struct { + xcb_atom_t from; + xkb_atom_t to; + } cache[256]; + size_t len; +}; + bool adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn, const xcb_atom_t *from, xkb_atom_t *to, const size_t count) @@ -163,24 +177,49 @@ adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn, xcb_get_atom_name_cookie_t cookies[SIZE]; const size_t num_batches = ROUNDUP(count, SIZE) / SIZE; + if (!ctx->x11_atom_cache) { + ctx->x11_atom_cache = calloc(1, sizeof(struct x11_atom_cache)); + } + /* Can be NULL in case the malloc failed. */ + struct x11_atom_cache *cache = ctx->x11_atom_cache; + if (cache && cache->conn != conn) { + cache->conn = conn; + cache->len = 0; + } + + memset(to, 0, count * sizeof(*to)); + /* Send and collect the atoms in batches of reasonable SIZE. */ for (size_t batch = 0; batch < num_batches; batch++) { const size_t start = batch * SIZE; const size_t stop = MIN((batch + 1) * SIZE, count); /* Send. */ - for (size_t i = start; i < stop; i++) - if (from[i] != XCB_ATOM_NONE) + for (size_t i = start; i < stop; i++) { + bool cache_hit = false; + if (cache) { + for (size_t c = 0; c < cache->len; c++) { + if (cache->cache[c].from == from[i]) { + to[i] = cache->cache[c].to; + cache_hit = true; + break; + } + } + } + if (!cache_hit && from[i] != XCB_ATOM_NONE) cookies[i % SIZE] = xcb_get_atom_name(conn, from[i]); + } /* Collect. */ for (size_t i = start; i < stop; i++) { xcb_get_atom_name_reply_t *reply; - if (from[i] == XCB_ATOM_NONE) { - to[i] = XKB_ATOM_NONE; + if (from[i] == XCB_ATOM_NONE) + continue; + + /* Was filled from cache. */ + if (to[i] != 0) continue; - } reply = xcb_get_atom_name_reply(conn, cookies[i % SIZE], NULL); if (!reply) @@ -194,6 +233,12 @@ adopt_atoms(struct xkb_context *ctx, xcb_connection_t *conn, if (to[i] == XKB_ATOM_NONE) goto err_discard; + if (cache && cache->len < ARRAY_SIZE(cache->cache)) { + size_t idx = cache->len++; + cache->cache[idx].from = from[i]; + cache->cache[idx].to = to[i]; + } + continue; /*