aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-05-27 09:40:40 +0800
committerPo Lu2022-05-27 09:40:40 +0800
commitc0807daedc22812add26f9f9be8d9b68afac1217 (patch)
treebd6855b19f3cd9d2abeec55eec93ad84d7850a1d /src
parent8dcebc96299149845d63e23f27c75a1ecc0b3538 (diff)
downloademacs-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.c51
-rw-r--r--src/xterm.h3
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