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

[PATCH v2 2/4] commit-queue: LIFO or priority queue of commits

From
Junio C Hamano <gitster@pobox.com>
Date
Jun 9, 2013, 23:24 UTC
Message-ID
<1370820277-30158-3-git-send-email-gitster@pobox.com>
In-Reply-To
<1370820277-30158-1-git-send-email-gitster@pobox.com>

Traditionally we used a singly linked list of commits to hold a set of in-flight commits while traversing history. The most typical use of the list is to add commits that are newly discovered to it, keep the list sorted by commit timestamp, pick up the newest one from the list, and keep digging. The cost of keeping the singly linked list sorted is nontrivial, and this typical use pattern better matches a priority queue.

Introduce a commit-queue structure, that can be used either as a LIFO stack, or a priority queue. This will be used in the next patch to hold in-flight commits during sort-in-topological-order.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Makefile       |  2 ++
 commit-queue.c | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 commit-queue.h | 31 +++++++++++++++++++++++++
 3 files changed, 104 insertions(+)
 create mode 100644 commit-queue.c
 create mode 100644 commit-queue.h
diff --git a/Makefile b/Makefile
index 598d631..3cf55e9 100644
--- a/Makefile
+++ b/Makefile
@@ -634,6 +634,7 @@ LIB_H += cache.h
 LIB_H += color.h
 LIB_H += column.h
 LIB_H += commit.h
+LIB_H += commit-queue.h
 LIB_H += compat/bswap.h
 LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
@@ -757,6 +758,7 @@ LIB_OBJS += color.o
 LIB_OBJS += column.o
 LIB_OBJS += combine-diff.o
 LIB_OBJS += commit.o
+LIB_OBJS += commit-queue.o
 LIB_OBJS += compat/obstack.o
 LIB_OBJS += compat/terminal.o
 LIB_OBJS += config.o
diff --git a/commit-queue.c b/commit-queue.c
new file mode 100644
index 0000000..77d4b02
--- /dev/null
+++ b/commit-queue.c
@@ -0,0 +1,71 @@
+#include "cache.h"
+#include "commit.h"
+#include "commit-queue.h"
+
+void clear_commit_queue(struct commit_queue *queue)
+{
+	free(queue->array);
+	queue->nr = 0;
+	queue->alloc = 0;
+	queue->array = NULL;
+}
+
+void commit_queue_put(struct commit_queue *queue, struct commit *commit)
+{
+	commit_compare_fn compare = queue->compare;
+	int ix, parent;
+
+	/* Append at the end */
+	ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
+	queue->array[queue->nr++] = commit;
+	if (!compare)
+		return; /* LIFO */
+
+	/* Bubble up the new one */
+	for (ix = queue->nr - 1; ix; ix = parent) {
+		parent = (ix - 1) / 2;
+		if (compare(queue->array[parent], queue->array[ix],
+			    queue->cb_data) < 0)
+			break;
+
+		commit = queue->array[parent];
+		queue->array[parent] = queue->array[ix];
+		queue->array[ix] = commit;
+	}
+}
+
+struct commit *commit_queue_get(struct commit_queue *queue)
+{
+	struct commit *result, *swap;
+	int ix, child;
+	commit_compare_fn compare = queue->compare;
+
+	if (!queue->nr)
+		return NULL;
+	if (!compare)
+		return queue->array[--queue->nr]; /* LIFO */
+
+	result = queue->array[0];
+	if (!--queue->nr)
+		return result;
+
+	queue->array[0] = queue->array[queue->nr];
+
+	/* Push down the one at the root */
+	for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
+		child = ix * 2 + 1; /* left */
+		if ((child + 1 < queue->nr) &&
+		    (compare(queue->array[child], queue->array[child + 1],
+			     queue->cb_data) >= 0))
+			child++; /* use right child */
+
+		if (compare(queue->array[ix], queue->array[child],
+			    queue->cb_data) < 0)
+			break;
+
+		swap = queue->array[child];
+		queue->array[child] = queue->array[ix];
+		queue->array[ix] = swap;
+	}
+	return result;
+}
diff --git a/commit-queue.h b/commit-queue.h
new file mode 100644
index 0000000..7c5dc4c
--- /dev/null
+++ b/commit-queue.h
@@ -0,0 +1,31 @@
+#ifndef COMMIT_QUEUE_H
+#define COMMIT_QUEUE_H
+
+/*
+ * Compare two commits; the third parameter is cb_data in the
+ * commit_queue structure.
+ */
+typedef int (*commit_compare_fn)(struct commit *, struct commit *, void *);
+
+struct commit_queue {
+	commit_compare_fn compare;
+	void *cb_data;
+	int alloc, nr;
+	struct commit **array;
+};
+
+/*
+ * Add the commit to the queue
+ */
+extern void commit_queue_put(struct commit_queue *, struct commit *);
+
+/*
+ * Extract the commit that compares the smallest out of the queue,
+ * or NULL.  If compare function is NULL, the queue acts as a LIFO
+ * stack.
+ */
+extern struct commit *commit_queue_get(struct commit_queue *);
+
+extern void clear_commit_queue(struct commit_queue *);
+
+#endif /* COMMIT_QUEUE_H */
-- 
1.8.3-451-gb703ddf
Previous: Jeff KingNext: Jeff King
Message 23 of 51 in “add --authorship-order flag to git log / rev-list”
  1. add --authorship-order flag to git log / rev-listelliottcable, Jun 4, 2013
  2. rev-list: add --authorship-order alternative orderingelliottcable, Jun 4, 2013
  3. Junio C HamanoJun 4, 2013
  4. Junio C HamanoJun 4, 2013
  5. Elliott CableJun 6, 2013
  6. Junio C HamanoJun 6, 2013
  7. Elliott CableJun 6, 2013
  8. Junio C HamanoJun 6, 2013
  9. Junio C HamanoJun 6, 2013
  10. toposort: rename "lifo" fieldJunio C Hamano, Jun 6, 2013
  11. Junio C HamanoJun 7, 2013
  12. 0/3 Preparing for --date-order=authorJunio C Hamano, Jun 7, 2013
  13. 1/3 toposort: rename "lifo" fieldJunio C Hamano, Jun 7, 2013
  14. Eric SunshineJun 7, 2013
  15. Junio C HamanoJun 7, 2013
  16. 2/3 commit-queue: LIFO or priority queue of commitsJunio C Hamano, Jun 7, 2013
  17. Eric SunshineJun 7, 2013
  18. 3/3 sort-in-topological-order: use commit-queueJunio C Hamano, Jun 7, 2013
  19. 0/4 log --author-date-orderJunio C Hamano, Jun 9, 2013
  20. 1/4 toposort: rename "lifo" fieldJunio C Hamano, Jun 9, 2013
  21. Eric SunshineJun 10, 2013
  22. Jeff KingJun 10, 2013
  23. 2/4 commit-queue: LIFO or priority queue of commitsJunio C Hamano, Jun 9, 2013
  24. Jeff KingJun 10, 2013
  25. Junio C HamanoJun 10, 2013
  26. Jeff KingJun 10, 2013
  27. Junio C HamanoJun 10, 2013
  28. Jeff KingJun 10, 2013
  29. Junio C HamanoJun 10, 2013
  30. Jeff KingJun 11, 2013
  31. Junio C HamanoJun 11, 2013
  32. 0/4 log --author-date-orderJunio C Hamano, Jun 11, 2013
  33. 1/4 toposort: rename "lifo" fieldJunio C Hamano, Jun 11, 2013
  34. 2/4 prio-queue: priority queue of pointers to structsJunio C Hamano, Jun 11, 2013
  35. 3/4 sort-in-topological-order: use prio-queueJunio C Hamano, Jun 11, 2013
  36. 4/4 log: --author-date-orderJunio C Hamano, Jun 11, 2013
  37. 3/4 sort-in-topological-order: use commit-queueJunio C Hamano, Jun 9, 2013
  38. Junio C HamanoJun 9, 2013
  39. Jeff KingJun 10, 2013
  40. Junio C HamanoJun 10, 2013
  41. Jeff KingJun 10, 2013
  42. 4/4 log: --author-date-orderJunio C Hamano, Jun 9, 2013
  43. Jeff KingJun 10, 2013
  44. Junio C HamanoJun 10, 2013
  45. Jeff KingJun 10, 2013
  46. Junio C HamanoJun 20, 2013
  47. Jeff KingJun 20, 2013
  48. Eric SunshineJun 7, 2013
  49. Jeff KingJun 4, 2013
  50. Junio C HamanoJun 4, 2013
  51. Elliott CableJun 6, 2013

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.