git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 Outreachy] mru: use double-linked list from list.h

From
Olga Telezhnaya <olyatelezhnaya@gmail.com>
Date
Sep 30, 2017, 17:51 UTC
Message-ID
<0102015ed3e9b1a8-74821a55-aa9a-4e5a-b267-c3d2462e3eed-000000@eu-west-1.amazonses.com>
In-Reply-To
<0102015ec7a3424b-529be659-bdb6-42c4-a48f-db264f33d53a-000000@eu-west-1.amazonses.com>

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.

Signed-off-by: Olga Telezhnaia <olyatelezhnaya@gmail.com>
Mentored-by: Christian Couder <christian.couder@gmail.com>
Mentored by: Jeff King <peff@peff.net>
---
 builtin/pack-objects.c |  5 +++--
 mru.c                  | 49 +++++++++++++------------------------------------
 mru.h                  | 31 +++++++++++++------------------
 packfile.c             |  7 ++++---
 4 files changed, 33 insertions(+), 59 deletions(-)
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f721137eaf881..ba812349e0aab 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -995,8 +995,8 @@ static int want_object_in_pack(const unsigned char *sha1,
 			       struct packed_git **found_pack,
 			       off_t *found_offset)
 {
-	struct mru_entry *entry;
 	int want;
+	struct list_head *pos;
 
 	if (!exclude && local && has_loose_object_nonlocal(sha1))
 		return 0;
@@ -1012,7 +1012,8 @@ static int want_object_in_pack(const unsigned char *sha1,
 			return want;
 	}
 
-	for (entry = packed_git_mru.head; entry; entry = entry->next) {
+	list_for_each(pos, &packed_git_mru.list) {
+		struct mru *entry = list_entry(pos, struct mru, list);
 		struct packed_git *p = entry->item;
 		off_t offset;
 
diff --git a/mru.c b/mru.c
index 9dedae0287ed2..8f3f34c5ba91d 100644
--- a/mru.c
+++ b/mru.c
@@ -1,50 +1,27 @@
 #include "cache.h"
 #include "mru.h"
 
-void mru_append(struct mru *mru, void *item)
+void mru_append(struct mru *head, void *item)
 {
-	struct mru_entry *cur = xmalloc(sizeof(*cur));
+	struct mru *cur = xmalloc(sizeof(*cur));
 	cur->item = item;
-	cur->prev = mru->tail;
-	cur->next = NULL;
-
-	if (mru->tail)
-		mru->tail->next = cur;
-	else
-		mru->head = cur;
-	mru->tail = cur;
+	list_add_tail(&cur->list, &head->list);
 }
 
-void mru_mark(struct mru *mru, struct mru_entry *entry)
+void mru_mark(struct mru *head, struct mru *entry)
 {
-	/* If we're already at the front of the list, nothing to do */
-	if (mru->head == entry)
-		return;
-
-	/* Otherwise, remove us from our current slot... */
-	if (entry->prev)
-		entry->prev->next = entry->next;
-	if (entry->next)
-		entry->next->prev = entry->prev;
-	else
-		mru->tail = entry->prev;
-
-	/* And insert us at the beginning. */
-	entry->prev = NULL;
-	entry->next = mru->head;
-	if (mru->head)
-		mru->head->prev = entry;
-	mru->head = entry;
+	/* To mark means to put at the front of the list. */
+	list_del(&entry->list);
+	list_add(&entry->list, &head->list);
 }
 
-void mru_clear(struct mru *mru)
+void mru_clear(struct mru *head)
 {
-	struct mru_entry *p = mru->head;
+	struct list_head *pos;
+	struct list_head *tmp;
 
-	while (p) {
-		struct mru_entry *to_free = p;
-		p = p->next;
-		free(to_free);
+	list_for_each_safe(pos, tmp, &head->list) {
+		free(list_entry(pos, struct mru, list));
 	}
-	mru->head = mru->tail = NULL;
+	INIT_LIST_HEAD(&head->list);
 }
diff --git a/mru.h b/mru.h
index 42e4aeaa1098a..80a589eb4c0eb 100644
--- a/mru.h
+++ b/mru.h
@@ -1,6 +1,8 @@
 #ifndef MRU_H
 #define MRU_H
 
+#include "list.h"
+
 /**
  * A simple most-recently-used cache, backed by a doubly-linked list.
  *
@@ -8,18 +10,15 @@
  *
  *   // Create a list.  Zero-initialization is required.
  *   static struct mru cache;
- *   mru_append(&cache, item);
- *   ...
+ *   INIT_LIST_HEAD(&cache.list);
  *
- *   // Iterate in MRU order.
- *   struct mru_entry *p;
- *   for (p = cache.head; p; p = p->next) {
- *	if (matches(p->item))
- *		break;
- *   }
+ *   // Add new item to the end of the list.
+ *   void *item;
+ *   ...
+ *   mru_append(&cache, item);
  *
  *   // Mark an item as used, moving it to the front of the list.
- *   mru_mark(&cache, p);
+ *   mru_mark(&cache, item);
  *
  *   // Reset the list to empty, cleaning up all resources.
  *   mru_clear(&cache);
@@ -29,17 +28,13 @@
  * you will begin traversing the whole list again.
  */
 
-struct mru_entry {
-	void *item;
-	struct mru_entry *prev, *next;
-};
-
 struct mru {
-	struct mru_entry *head, *tail;
+	struct list_head list;
+	void *item;
 };
 
-void mru_append(struct mru *mru, void *item);
-void mru_mark(struct mru *mru, struct mru_entry *entry);
-void mru_clear(struct mru *mru);
+void mru_append(struct mru *head, void *item);
+void mru_mark(struct mru *head, struct mru *entry);
+void mru_clear(struct mru *head);
 
 #endif /* MRU_H */
diff --git a/packfile.c b/packfile.c
index f69a5c8d607af..502d915991bee 100644
--- a/packfile.c
+++ b/packfile.c
@@ -40,7 +40,7 @@ static unsigned int pack_max_fds;
 static size_t peak_pack_mapped;
 static size_t pack_mapped;
 struct packed_git *packed_git;
-struct mru packed_git_mru;
+struct mru packed_git_mru = {{&packed_git_mru.list, &packed_git_mru.list}};
 
 #define SZ_FMT PRIuMAX
 static inline uintmax_t sz_fmt(size_t s) { return s; }
@@ -1824,13 +1824,14 @@ static int fill_pack_entry(const unsigned char *sha1,
  */
 int find_pack_entry(const unsigned char *sha1, struct pack_entry *e)
 {
-	struct mru_entry *p;
+	struct list_head *pos;
 
 	prepare_packed_git();
 	if (!packed_git)
 		return 0;
 
-	for (p = packed_git_mru.head; p; p = p->next) {
+	list_for_each(pos, &packed_git_mru.list) {
+		struct mru *p = list_entry(pos, struct mru, list);
 		if (fill_pack_entry(sha1, e, p->item)) {
 			mru_mark(&packed_git_mru, p);
 			return 1;

--
https://github.com/git/git/pull/409
Previous: Junio C HamanoNext: Jeff King
Message 20 of 26 in “[Outreachy] cleanup: use list.h in mru.h and mru.c”
  1. [Outreachy] cleanup: use list.h in mru.h and mru.cОля Тележная, Sep 27, 2017
  2. Christian CouderSep 27, 2017
  3. mru: use double-linked list from list.hOlga Telezhnaya, Sep 28, 2017
  4. Junio C HamanoSep 28, 2017
  5. Jeff KingSep 28, 2017
  6. Junio C HamanoSep 28, 2017
  7. Jeff KingSep 28, 2017
  8. Jeff KingSep 28, 2017
  9. Jeff KingSep 28, 2017
  10. Christian CouderSep 29, 2017
  11. Jeff KingSep 29, 2017
  12. Christian CouderSep 29, 2017
  13. Оля ТележнаяSep 29, 2017
  14. Оля ТележнаяSep 29, 2017
  15. Jeff KingSep 29, 2017
  16. Оля ТележнаяSep 30, 2017
  17. Jeff KingOct 2, 2017
  18. Jeff KingSep 29, 2017
  19. Junio C HamanoSep 30, 2017
  20. mru: use double-linked list from list.hOlga Telezhnaya, Sep 30, 2017
  21. Jeff KingOct 2, 2017
  22. Оля ТележнаяOct 2, 2017
  23. Jeff KingOct 3, 2017
  24. Junio C HamanoNov 8, 2017
  25. Jeff KingNov 8, 2017
  26. Оля ТележнаяNov 10, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.