atom: get_atom now requires explicit xcb_connection_t

This is to make the access to X server more explicit, and make managing
the lifetime of xcb_connection_t a bit easier.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-02-16 00:31:53 +00:00
parent 6315faed20
commit a93bbc30e5
No known key found for this signature in database
GPG Key ID: D3A4405BE6CC17F4
6 changed files with 30 additions and 38 deletions

View File

@ -8,13 +8,11 @@
#include "log.h"
#include "utils.h"
static inline int
atom_getter(struct cache *cache, const char *atom_name, struct cache_handle **value) {
struct atom *atoms = container_of(cache, struct atom, c);
static inline int atom_getter(struct cache *cache attr_unused, const char *atom_name,
struct cache_handle **value, void *user_data) {
xcb_connection_t *c = user_data;
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(
atoms->conn,
xcb_intern_atom(atoms->conn, 0, to_u16_checked(strlen(atom_name)), atom_name),
NULL);
c, xcb_intern_atom(c, 0, to_u16_checked(strlen(atom_name)), atom_name), NULL);
xcb_atom_t atom = XCB_NONE;
if (reply) {
@ -38,14 +36,22 @@ atom_entry_free(struct cache *cache attr_unused, struct cache_handle *handle) {
free(entry);
}
xcb_atom_t get_atom(struct atom *a, const char *key, xcb_connection_t *c) {
struct cache_handle *entry = NULL;
if (cache_get_or_fetch(&a->c, key, &entry, c, atom_getter) < 0) {
log_error("Failed to get atom %s", key);
return XCB_NONE;
}
return cache_entry(entry, struct atom_entry, entry)->atom;
}
/**
* Create a new atom structure and fetch all predefined atoms
*/
struct atom *init_atoms(xcb_connection_t *c) {
auto atoms = ccalloc(1, struct atom);
atoms->conn = c;
cache_init(&atoms->c, atom_getter);
#define ATOM_GET(x) atoms->a##x = get_atom(atoms, #x)
atoms->c = CACHE_INIT;
#define ATOM_GET(x) atoms->a##x = get_atom(atoms, #x, c)
LIST_APPLY(ATOM_GET, SEP_COLON, ATOM_LIST1);
LIST_APPLY(ATOM_GET, SEP_COLON, ATOM_LIST2);
#undef ATOM_GET

View File

@ -55,7 +55,6 @@
#define ATOM_DEF(x) xcb_atom_t a##x
struct atom {
xcb_connection_t *conn;
struct cache c;
LIST_APPLY(ATOM_DEF, SEP_COLON, ATOM_LIST1);
LIST_APPLY(ATOM_DEF, SEP_COLON, ATOM_LIST2);
@ -66,20 +65,11 @@ struct atom_entry {
xcb_atom_t atom;
};
/// Create a new atom object with a xcb connection, note that this atom object will hold a
/// reference to the connection, so the caller must keep the connection alive until the
/// atom object is destroyed.
struct atom *init_atoms(xcb_connection_t *);
static inline xcb_atom_t get_atom(struct atom *a, const char *key) {
struct cache_handle *entry = NULL;
if (cache_get_or_fetch(&a->c, key, &entry) < 0) {
log_error("Failed to get atom %s", key);
return XCB_NONE;
}
return cache_entry(entry, struct atom_entry, entry)->atom;
}
/// Create a new atom object with a xcb connection. `struct atom` does not hold
/// a reference to the connection.
struct atom *init_atoms(xcb_connection_t *c);
xcb_atom_t get_atom(struct atom *a, const char *key, xcb_connection_t *c);
static inline xcb_atom_t get_atom_cached(struct atom *a, const char *key) {
return cache_entry(cache_get(&a->c, key), struct atom_entry, entry)->atom;
}

View File

@ -1047,7 +1047,7 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) {
// Get target atom if it's not a predefined one
if (pleaf->predef == C2_L_PUNDEFINED) {
pleaf->tgtatom = get_atom(ps->atoms, pleaf->tgt);
pleaf->tgtatom = get_atom(ps->atoms, pleaf->tgt, ps->c.c);
if (!pleaf->tgtatom) {
log_error("Failed to get atom for target \"%s\".", pleaf->tgt);
return false;

View File

@ -8,13 +8,14 @@ struct cache_handle *cache_get(struct cache *c, const char *key) {
return e;
}
int cache_get_or_fetch(struct cache *c, const char *key, struct cache_handle **value) {
int cache_get_or_fetch(struct cache *c, const char *key, struct cache_handle **value,
void *user_data, cache_getter_t getter) {
*value = cache_get(c, key);
if (*value) {
return 0;
}
int err = c->getter(c, key, value);
int err = getter(c, key, value, user_data);
assert(err <= 0);
if (err < 0) {
return err;
@ -49,8 +50,3 @@ void cache_invalidate_all(struct cache *c, cache_free_t free_fn) {
cache_invalidate_impl(c, e, free_fn);
}
}
void cache_init(struct cache *cache, cache_getter_t getter) {
cache->getter = getter;
cache->entries = NULL;
}

View File

@ -12,27 +12,27 @@ struct cache_handle;
/// Should return 0 if the value is fetched successfully, and a negative number if the
/// value cannot be fetched. Getter doesn't need to initialize fields of `struct
/// cache_handle`.
typedef int (*cache_getter_t)(struct cache *, const char *key, struct cache_handle **value);
typedef int (*cache_getter_t)(struct cache *, const char *key,
struct cache_handle **value, void *user_data);
typedef void (*cache_free_t)(struct cache *, struct cache_handle *value);
struct cache {
cache_getter_t getter;
struct cache_handle *entries;
};
static const struct cache CACHE_INIT = {NULL};
struct cache_handle {
char *key;
UT_hash_handle hh;
};
/// Initialize a cache with `getter`
void cache_init(struct cache *cache, cache_getter_t getter);
/// Get a value from the cache. If the value doesn't present in the cache yet, the
/// getter will be called, and the returned value will be stored into the cache.
/// Returns 0 if the value is already present in the cache, 1 if the value is fetched
/// successfully, and a negative number if the value cannot be fetched.
int cache_get_or_fetch(struct cache *, const char *key, struct cache_handle **value);
int cache_get_or_fetch(struct cache *, const char *key, struct cache_handle **value,
void *user_data, cache_getter_t getter);
/// Get a value from the cache. If the value doesn't present in the cache, NULL will be
/// returned.

View File

@ -1346,7 +1346,7 @@ static int register_cm(session_t *ps) {
log_fatal("Failed to allocate memory");
return -1;
}
atom = get_atom(ps->atoms, buf);
atom = get_atom(ps->atoms, buf, ps->c.c);
free(buf);
xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(