delta_base_cache: use list.h for LRU

We keep an LRU list of entries for when we need to drop something from an over-full cache. The list is implemented as a circular doubly-linked list, which is exactly what list.h provides. We can save a few lines by using the list.h macros and functions. More importantly, this makes the code easier to follow, as the reader sees explicit concepts like "list_add_tail()" instead of pointer manipulation. As a bonus, the list_entry() macro lets us place the lru pointers anywhere inside the delta_base_cache_entry struct (as opposed to just casting the pointer, which requires it at the front of the struct). This will be useful in later patches when we need to place other items at the front of the struct (e.g., our hashmap implementation requires this). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Aug 22, 2016 at 17:59 UTC 12d95ef6fcc1f0b83b24e926f488c6416c08d79c
1 file changed +16 -22
sha1_file.c
+16 -22
@@ -24,6 +24,7 @@
24 #include "streaming.h"
25 #include "dir.h"
26 #include "mru.h"
27 +#include "list.h"
28
29 #ifndef O_NOATIME
30 #if defined(__linux__) && (defined(__i386__) || defined(__PPC__))
@@ -2077,13 +2078,10 @@ static void *unpack_compressed_entry(struct packed_git *p,
2078
2079 static size_t delta_base_cached;
2080
2080 -static struct delta_base_cache_lru_list {
2081 - struct delta_base_cache_lru_list *prev;
2082 - struct delta_base_cache_lru_list *next;
2083 -} delta_base_cache_lru = { &delta_base_cache_lru, &delta_base_cache_lru };
2081 +static LIST_HEAD(delta_base_cache_lru);
2082
2083 static struct delta_base_cache_entry {
2086 - struct delta_base_cache_lru_list lru;
2084 + struct list_head lru;
2085 void *data;
2086 struct packed_git *p;
2087 off_t base_offset;
@@ -2128,8 +2126,7 @@ static int in_delta_base_cache(struct packed_git *p, off_t base_offset)
2126 static void detach_delta_base_cache_entry(struct delta_base_cache_entry *ent)
2127 {
2128 ent->data = NULL;
2131 - ent->lru.next->prev = ent->lru.prev;
2132 - ent->lru.prev->next = ent->lru.next;
2129 + list_del(&ent->lru);
2130 delta_base_cached -= ent->size;
2131 }
2132
@@ -2168,24 +2165,24 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
2165 {
2166 unsigned long hash = pack_entry_hash(p, base_offset);
2167 struct delta_base_cache_entry *ent = delta_base_cache + hash;
2171 - struct delta_base_cache_lru_list *lru;
2168 + struct list_head *lru;
2169
2170 release_delta_base_cache(ent);
2171 delta_base_cached += base_size;
2172
2176 - for (lru = delta_base_cache_lru.next;
2177 - delta_base_cached > delta_base_cache_limit
2178 - && lru != &delta_base_cache_lru;
2179 - lru = lru->next) {
2180 - struct delta_base_cache_entry *f = (void *)lru;
2173 + list_for_each(lru, &delta_base_cache_lru) {
2174 + struct delta_base_cache_entry *f =
2175 + list_entry(lru, struct delta_base_cache_entry, lru);
2176 + if (delta_base_cached <= delta_base_cache_limit)
2177 + break;
2178 if (f->type == OBJ_BLOB)
2179 release_delta_base_cache(f);
2180 }
2184 - for (lru = delta_base_cache_lru.next;
2185 - delta_base_cached > delta_base_cache_limit
2186 - && lru != &delta_base_cache_lru;
2187 - lru = lru->next) {
2188 - struct delta_base_cache_entry *f = (void *)lru;
2181 + list_for_each(lru, &delta_base_cache_lru) {
2182 + struct delta_base_cache_entry *f =
2183 + list_entry(lru, struct delta_base_cache_entry, lru);
2184 + if (delta_base_cached <= delta_base_cache_limit)
2185 + break;
2186 release_delta_base_cache(f);
2187 }
2188
@@ -2194,10 +2191,7 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset,
2191 ent->type = type;
2192 ent->data = base;
2193 ent->size = base_size;
2197 - ent->lru.next = &delta_base_cache_lru;
2198 - ent->lru.prev = delta_base_cache_lru.prev;
2199 - delta_base_cache_lru.prev->next = &ent->lru;
2200 - delta_base_cache_lru.prev = &ent->lru;
2194 + list_add_tail(&ent->lru, &delta_base_cache_lru);
2195 }
2196
2197 static void *read_object(const unsigned char *sha1, enum object_type *type,