diff options
| author | Po Lu | 2022-05-27 09:40:40 +0800 |
|---|---|---|
| committer | Po Lu | 2022-05-27 09:40:40 +0800 |
| commit | c0807daedc22812add26f9f9be8d9b68afac1217 (patch) | |
| tree | bd6855b19f3cd9d2abeec55eec93ad84d7850a1d /src | |
| parent | 8dcebc96299149845d63e23f27c75a1ecc0b3538 (diff) | |
| download | emacs-c0807daedc22812add26f9f9be8d9b68afac1217.tar.gz emacs-c0807daedc22812add26f9f9be8d9b68afac1217.zip | |
Improve lookup efficiency of color cache and prevent leaking
* src/xterm.c (x_parse_color): Move recently used colors to the
start of the cache and free unused entries when there are too
many.
(x_term_init, x_delete_display): Initialize and free new fields.
* src/xterm.h (struct x_display_info): New field
`color_names_length'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 51 | ||||
| -rw-r--r-- | src/xterm.h | 3 |
2 files changed, 52 insertions, 2 deletions
diff --git a/src/xterm.c b/src/xterm.c index 2c50b508151..5964a8bb483 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -7277,9 +7277,10 @@ x_parse_color (struct frame *f, const char *color_name, | |||
| 7277 | Display *dpy; | 7277 | Display *dpy; |
| 7278 | Colormap cmap; | 7278 | Colormap cmap; |
| 7279 | struct x_display_info *dpyinfo; | 7279 | struct x_display_info *dpyinfo; |
| 7280 | struct color_name_cache_entry *cache_entry; | 7280 | struct color_name_cache_entry *cache_entry, *last; |
| 7281 | struct color_name_cache_entry *next, *color_entry; | ||
| 7281 | unsigned int hash, idx; | 7282 | unsigned int hash, idx; |
| 7282 | int rc; | 7283 | int rc, i; |
| 7283 | 7284 | ||
| 7284 | /* Don't pass #RGB strings directly to XParseColor, because that | 7285 | /* Don't pass #RGB strings directly to XParseColor, because that |
| 7285 | follows the X convention of zero-extending each channel | 7286 | follows the X convention of zero-extending each channel |
| @@ -7306,16 +7307,31 @@ x_parse_color (struct frame *f, const char *color_name, | |||
| 7306 | hash = x_hash_string_ignore_case (color_name); | 7307 | hash = x_hash_string_ignore_case (color_name); |
| 7307 | idx = hash % dpyinfo->color_names_size; | 7308 | idx = hash % dpyinfo->color_names_size; |
| 7308 | 7309 | ||
| 7310 | last = NULL; | ||
| 7311 | |||
| 7309 | for (cache_entry = dpyinfo->color_names[idx]; | 7312 | for (cache_entry = dpyinfo->color_names[idx]; |
| 7310 | cache_entry; cache_entry = cache_entry->next) | 7313 | cache_entry; cache_entry = cache_entry->next) |
| 7311 | { | 7314 | { |
| 7312 | if (!xstrcasecmp (cache_entry->name, color_name)) | 7315 | if (!xstrcasecmp (cache_entry->name, color_name)) |
| 7313 | { | 7316 | { |
| 7317 | /* Move recently used entries to the start of the color | ||
| 7318 | cache. */ | ||
| 7319 | |||
| 7320 | if (last) | ||
| 7321 | { | ||
| 7322 | last->next = cache_entry->next; | ||
| 7323 | cache_entry->next = dpyinfo->color_names[idx]; | ||
| 7324 | |||
| 7325 | dpyinfo->color_names[idx] = cache_entry; | ||
| 7326 | } | ||
| 7327 | |||
| 7314 | if (cache_entry->valid) | 7328 | if (cache_entry->valid) |
| 7315 | *color = cache_entry->rgb; | 7329 | *color = cache_entry->rgb; |
| 7316 | 7330 | ||
| 7317 | return cache_entry->valid; | 7331 | return cache_entry->valid; |
| 7318 | } | 7332 | } |
| 7333 | |||
| 7334 | last = cache_entry; | ||
| 7319 | } | 7335 | } |
| 7320 | 7336 | ||
| 7321 | block_input (); | 7337 | block_input (); |
| @@ -7323,6 +7339,7 @@ x_parse_color (struct frame *f, const char *color_name, | |||
| 7323 | unblock_input (); | 7339 | unblock_input (); |
| 7324 | 7340 | ||
| 7325 | cache_entry = xzalloc (sizeof *cache_entry); | 7341 | cache_entry = xzalloc (sizeof *cache_entry); |
| 7342 | dpyinfo->color_names_length[idx] += 1; | ||
| 7326 | 7343 | ||
| 7327 | if (rc) | 7344 | if (rc) |
| 7328 | cache_entry->rgb = *color; | 7345 | cache_entry->rgb = *color; |
| @@ -7333,6 +7350,33 @@ x_parse_color (struct frame *f, const char *color_name, | |||
| 7333 | 7350 | ||
| 7334 | dpyinfo->color_names[idx] = cache_entry; | 7351 | dpyinfo->color_names[idx] = cache_entry; |
| 7335 | 7352 | ||
| 7353 | /* Don't let the color cache become too big. */ | ||
| 7354 | if (dpyinfo->color_names_length[idx] > 128) | ||
| 7355 | { | ||
| 7356 | i = 0; | ||
| 7357 | |||
| 7358 | for (last = dpyinfo->color_names[idx]; last; last = last->next) | ||
| 7359 | { | ||
| 7360 | if (++i == 128) | ||
| 7361 | { | ||
| 7362 | next = last->next; | ||
| 7363 | last->next = NULL; | ||
| 7364 | |||
| 7365 | for (color_entry = next; color_entry; color_entry = last) | ||
| 7366 | { | ||
| 7367 | last = color_entry->next; | ||
| 7368 | |||
| 7369 | xfree (color_entry->name); | ||
| 7370 | xfree (color_entry); | ||
| 7371 | |||
| 7372 | dpyinfo->color_names_length[idx] -= 1; | ||
| 7373 | } | ||
| 7374 | |||
| 7375 | return rc; | ||
| 7376 | } | ||
| 7377 | } | ||
| 7378 | } | ||
| 7379 | |||
| 7336 | return rc; | 7380 | return rc; |
| 7337 | } | 7381 | } |
| 7338 | 7382 | ||
| @@ -24511,6 +24555,8 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) | |||
| 24511 | dpyinfo->color_names_size = 256; | 24555 | dpyinfo->color_names_size = 256; |
| 24512 | dpyinfo->color_names = xzalloc (dpyinfo->color_names_size | 24556 | dpyinfo->color_names = xzalloc (dpyinfo->color_names_size |
| 24513 | * sizeof *dpyinfo->color_names); | 24557 | * sizeof *dpyinfo->color_names); |
| 24558 | dpyinfo->color_names_length = xzalloc (dpyinfo->color_names_size | ||
| 24559 | * sizeof *dpyinfo->color_names_length); | ||
| 24514 | 24560 | ||
| 24515 | /* Set the name of the terminal. */ | 24561 | /* Set the name of the terminal. */ |
| 24516 | terminal->name = xlispstrdup (display_name); | 24562 | terminal->name = xlispstrdup (display_name); |
| @@ -25248,6 +25294,7 @@ x_delete_display (struct x_display_info *dpyinfo) | |||
| 25248 | } | 25294 | } |
| 25249 | 25295 | ||
| 25250 | xfree (dpyinfo->color_names); | 25296 | xfree (dpyinfo->color_names); |
| 25297 | xfree (dpyinfo->color_names_length); | ||
| 25251 | xfree (dpyinfo->x_id_name); | 25298 | xfree (dpyinfo->x_id_name); |
| 25252 | xfree (dpyinfo->x_dnd_atoms); | 25299 | xfree (dpyinfo->x_dnd_atoms); |
| 25253 | xfree (dpyinfo->color_cells); | 25300 | xfree (dpyinfo->color_cells); |
diff --git a/src/xterm.h b/src/xterm.h index daeb1a4575f..fbb381d066e 100644 --- a/src/xterm.h +++ b/src/xterm.h | |||
| @@ -520,6 +520,9 @@ struct x_display_info | |||
| 520 | /* A cache mapping color names to RGB values. */ | 520 | /* A cache mapping color names to RGB values. */ |
| 521 | struct color_name_cache_entry **color_names; | 521 | struct color_name_cache_entry **color_names; |
| 522 | 522 | ||
| 523 | /* The number of buckets for each hash in that hash table. */ | ||
| 524 | ptrdiff_t *color_names_length; | ||
| 525 | |||
| 523 | /* The size of that hash table. */ | 526 | /* The size of that hash table. */ |
| 524 | int color_names_size; | 527 | int color_names_size; |
| 525 | 528 | ||