mru: use double-linked list from list.h

Simplify mru.[ch] and related code by reusing the double-linked list implementation from list.h instead of a custom one. This commit is an intermediate step. Our final goal is to get rid of mru.[ch] at all and inline all logic. Mentored-by: Christian Couder <christian.couder@gmail.com> Mentored by: Jeff King <peff@peff.net> Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Olga Telezhnaya committed Sep 30, 2017 at 17:51 UTC 8865859dfc346c61f0e75fa429c5d307bd27368c
4 files changed +33 -59
builtin/pack-objects.c
+3 -2
@@ -995,8 +995,8 @@ static int want_object_in_pack(const unsigned char *sha1,
995 struct packed_git **found_pack,
996 off_t *found_offset)
997 {
998 - struct mru_entry *entry;
998 int want;
999 + struct list_head *pos;
1000
1001 if (!exclude && local && has_loose_object_nonlocal(sha1))
1002 return 0;
@@ -1012,7 +1012,8 @@ static int want_object_in_pack(const unsigned char *sha1,
1012 return want;
1013 }
1014
1015 - for (entry = packed_git_mru.head; entry; entry = entry->next) {
1015 + list_for_each(pos, &packed_git_mru.list) {
1016 + struct mru *entry = list_entry(pos, struct mru, list);
1017 struct packed_git *p = entry->item;
1018 off_t offset;
1019
mru.c
+13 -36
@@ -1,50 +1,27 @@
1 #include "cache.h"
2 #include "mru.h"
3
4 -void mru_append(struct mru *mru, void *item)
4 +void mru_append(struct mru *head, void *item)
5 {
6 - struct mru_entry *cur = xmalloc(sizeof(*cur));
6 + struct mru *cur = xmalloc(sizeof(*cur));
7 cur->item = item;
8 - cur->prev = mru->tail;
9 - cur->next = NULL;
10 -
11 - if (mru->tail)
12 - mru->tail->next = cur;
13 - else
14 - mru->head = cur;
15 - mru->tail = cur;
8 + list_add_tail(&cur->list, &head->list);
9 }
10
18 -void mru_mark(struct mru *mru, struct mru_entry *entry)
11 +void mru_mark(struct mru *head, struct mru *entry)
12 {
20 - /* If we're already at the front of the list, nothing to do */
21 - if (mru->head == entry)
22 - return;
23 -
24 - /* Otherwise, remove us from our current slot... */
25 - if (entry->prev)
26 - entry->prev->next = entry->next;
27 - if (entry->next)
28 - entry->next->prev = entry->prev;
29 - else
30 - mru->tail = entry->prev;
31 -
32 - /* And insert us at the beginning. */
33 - entry->prev = NULL;
34 - entry->next = mru->head;
35 - if (mru->head)
36 - mru->head->prev = entry;
37 - mru->head = entry;
13 + /* To mark means to put at the front of the list. */
14 + list_del(&entry->list);
15 + list_add(&entry->list, &head->list);
16 }
17
40 -void mru_clear(struct mru *mru)
18 +void mru_clear(struct mru *head)
19 {
42 - struct mru_entry *p = mru->head;
20 + struct list_head *pos;
21 + struct list_head *tmp;
22
44 - while (p) {
45 - struct mru_entry *to_free = p;
46 - p = p->next;
47 - free(to_free);
23 + list_for_each_safe(pos, tmp, &head->list) {
24 + free(list_entry(pos, struct mru, list));
25 }
49 - mru->head = mru->tail = NULL;
26 + INIT_LIST_HEAD(&head->list);
27 }
mru.h
+13 -18
@@ -1,6 +1,8 @@
1 #ifndef MRU_H
2 #define MRU_H
3
4 +#include "list.h"
5 +
6 /**
7 * A simple most-recently-used cache, backed by a doubly-linked list.
8 *
@@ -8,18 +10,15 @@
10 *
11 * // Create a list. Zero-initialization is required.
12 * static struct mru cache;
11 - * mru_append(&cache, item);
12 - * ...
13 + * INIT_LIST_HEAD(&cache.list);
14 *
14 - * // Iterate in MRU order.
15 - * struct mru_entry *p;
16 - * for (p = cache.head; p; p = p->next) {
17 - * if (matches(p->item))
18 - * break;
19 - * }
15 + * // Add new item to the end of the list.
16 + * void *item;
17 + * ...
18 + * mru_append(&cache, item);
19 *
20 * // Mark an item as used, moving it to the front of the list.
22 - * mru_mark(&cache, p);
21 + * mru_mark(&cache, item);
22 *
23 * // Reset the list to empty, cleaning up all resources.
24 * mru_clear(&cache);
@@ -29,17 +28,13 @@
28 * you will begin traversing the whole list again.
29 */
30
32 -struct mru_entry {
33 - void *item;
34 - struct mru_entry *prev, *next;
35 -};
36 -
31 struct mru {
38 - struct mru_entry *head, *tail;
32 + struct list_head list;
33 + void *item;
34 };
35
41 -void mru_append(struct mru *mru, void *item);
42 -void mru_mark(struct mru *mru, struct mru_entry *entry);
43 -void mru_clear(struct mru *mru);
36 +void mru_append(struct mru *head, void *item);
37 +void mru_mark(struct mru *head, struct mru *entry);
38 +void mru_clear(struct mru *head);
39
40 #endif /* MRU_H */
packfile.c
+4 -3
@@ -40,7 +40,7 @@ static unsigned int pack_max_fds;
40 static size_t peak_pack_mapped;
41 static size_t pack_mapped;
42 struct packed_git *packed_git;
43 -struct mru packed_git_mru;
43 +struct mru packed_git_mru = {{&packed_git_mru.list, &packed_git_mru.list}};
44
45 #define SZ_FMT PRIuMAX
46 static inline uintmax_t sz_fmt(size_t s) { return s; }
@@ -1824,13 +1824,14 @@ static int fill_pack_entry(const unsigned char *sha1,
1824 */
1825 int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
1826 {
1827 - struct mru_entry *p;
1827 + struct list_head *pos;
1828
1829 prepare_packed_git();
1830 if (!packed_git)
1831 return 0;
1832
1833 - for (p = packed_git_mru.head; p; p = p->next) {
1833 + list_for_each(pos, &packed_git_mru.list) {
1834 + struct mru *p = list_entry(pos, struct mru, list);
1835 if (fill_pack_entry(sha1, e, p->item)) {
1836 mru_mark(&packed_git_mru, p);
1837 return 1;