Signed-off-by: Tomek Grabiec <[email protected]>
---
Makefile | 3 +-
include/vm/list.h | 41 ++++++++++++++++++
test/vm/Makefile | 1 +
test/vm/list-test.c | 46 ++++++++++++++++++++
vm/list.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 205 insertions(+), 1 deletions(-)
create mode 100644 vm/list.c
diff --git a/Makefile b/Makefile
index ef99405..2006636 100644
--- a/Makefile
+++ b/Makefile
@@ -93,7 +93,8 @@ VM_OBJS = \
vm/string.o \
vm/types.o \
vm/zalloc.o \
- vm/class.o
+ vm/class.o \
+ vm/list.o
JAMVM_OBJS = \
vm/jato.o \
diff --git a/include/vm/list.h b/include/vm/list.h
index b94e737..e723fb3 100644
--- a/include/vm/list.h
+++ b/include/vm/list.h
@@ -4,6 +4,7 @@
#include <vm/system.h>
#include <stdbool.h>
+#include <memory.h>
/*
* This doubly-linked list is shamelessly stolen from Linux kernel.
@@ -190,4 +191,44 @@ static inline struct list_head *list_last(struct list_head
*head)
return head->prev;
}
+/**
+ * list_move_all - move one list to another
+ * @to: list head that elements from @from will be linked to
+ * @from: source list
+ */
+static inline void list_move_all(struct list_head *to, struct list_head *from)
+{
+ to->next = from->next;
+ to->prev = from->prev;
+ to->prev->next = to;
+ to->next->prev = to;
+}
+
+/**
+ * __list_sort - sort the list using given comparator with merge-sort algorithm
+ * @head: is a head of the list to be sorted
+ * @member_offset: is machine offset inside the list entry structure to the
+ * field of type struct list_head which links that entry with
+ * the list.
+ */
+extern void __list_sort(struct list_head * head,
+ int member_offset,
+ int (*comparator)(void*,void*));
+
+/**
+ * list_sort - wrapper for __list_sort
+ * @head: is a head of the list to be sorted
+ * @type: is the type of list entry
+ * @member: is the name of the field inside entry that links that entry with
+ * other entries in the list.
+ * @comaprator: function comparing two entries, should return value lesser
+ * than 0 when the first argument is lesser than the second one.
+ */
+#define list_sort(head,type,member,comparator) \
+ ({ \
+ __list_sort(head, \
+ offsetof(type, member), \
+ (int (*)(void*, void*)) comparator); \
+ })
+
#endif
diff --git a/test/vm/Makefile b/test/vm/Makefile
index f3480db..9e065ad 100644
--- a/test/vm/Makefile
+++ b/test/vm/Makefile
@@ -14,6 +14,7 @@ OBJS = \
../../vm/string.o \
../../vm/zalloc.o \
../../vm/types.o \
+ ../../vm/list.o \
bitset-test.o \
buffer-test.o \
bytecodes-test.o \
diff --git a/test/vm/list-test.c b/test/vm/list-test.c
index 455a57f..a10698f 100644
--- a/test/vm/list-test.c
+++ b/test/vm/list-test.c
@@ -63,3 +63,49 @@ void test_list_entry(void)
assert_ptr_equals(&foo, list_entry(&foo.node, struct foo, node));
}
+
+struct test_list_el {
+ int value;
+ struct list_head test_list_node;
+};
+
+int test_list_sort_comparator(struct test_list_el *e1, struct test_list_el *e2)
+{
+ return e1->value - e2->value;
+}
+
+void test_list_sort(void)
+{
+ struct list_head test_list;
+ struct test_list_el *el, *next;
+ struct test_list_el te1 = {.value = 1};
+ struct test_list_el te2 = {.value = 2};
+ struct test_list_el te3 = {.value = 3};
+ struct test_list_el te4 = {.value = 4};
+ struct test_list_el te5 = {.value = 5};
+ struct test_list_el te6 = {.value = 6};
+ struct test_list_el te7 = {.value = 7};
+
+ const int expected[] = {1, 2, 3, 4, 5, 6, 7};
+ int i;
+
+ INIT_LIST_HEAD(&test_list);
+ list_add_tail(&te2.test_list_node, &test_list);
+ list_add_tail(&te6.test_list_node, &test_list);
+ list_add_tail(&te4.test_list_node, &test_list);
+ list_add_tail(&te5.test_list_node, &test_list);
+ list_add_tail(&te7.test_list_node, &test_list);
+ list_add_tail(&te1.test_list_node, &test_list);
+ list_add_tail(&te3.test_list_node, &test_list);
+
+ list_sort(&test_list,
+ struct test_list_el,
+ test_list_node,
+ test_list_sort_comparator);
+
+ i = 0;
+ list_for_each_entry_safe(el, next, &test_list, test_list_node) {
+ assert_int_equals(el->value, expected[i]);
+ i++;
+ }
+}
diff --git a/vm/list.c b/vm/list.c
new file mode 100644
index 0000000..b239509
--- /dev/null
+++ b/vm/list.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009 Tomasz Grabiec
+ *
+ * This file is released under the GPL version 2 with the following
+ * clarification and special exception:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under terms
+ * of your choice, provided that you also meet, for each linked independent
+ * module, the terms and conditions of the license of that module. An
+ * independent module is a module which is not derived from or based on
+ * this library. If you modify this library, you may extend this exception
+ * to your version of the library, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version.
+ *
+ * Please refer to the file LICENSE for details.
+ */
+
+#include "vm/list.h"
+
+void __list_sort(struct list_head * head,
+ int member_offset,
+ int (*comparator)(void*, void*))
+{
+ struct list_head output_list;
+ struct list_head *input;
+ struct list_head *tmp;
+ struct list_head *output;
+ struct list_head *p, *q;
+ int i;
+ int k;
+ int pcount;
+ int qcount;
+ int nmerge;
+
+ input = head;
+ output = &output_list;
+ INIT_LIST_HEAD(output);
+ k = 1;
+
+ do {
+ p = input->next;
+ q = p;
+ nmerge = 0;
+
+ while (p != input) {
+ nmerge++;
+ pcount = 0;
+ qcount = k;
+
+ for (i=0; i<k && q!=input; i++) {
+ q = q->next;
+ pcount++;
+ }
+
+ while (pcount && qcount && q!=input) {
+ struct list_head *sel;
+ void *p_entry;
+ void *q_entry;
+
+ p_entry = (void*)p - member_offset;
+ q_entry = (void*)q - member_offset;
+
+ if (comparator(p_entry, q_entry) <= 0) {
+ sel = p;
+ pcount--;
+ p = p->next;
+ } else {
+ sel = q;
+ qcount--;
+ q = q->next;
+ }
+
+ list_del(sel);
+ list_add_tail(sel, output);
+ }
+
+ while (pcount--) {
+ struct list_head *next;
+
+ next = p->next;
+ list_del(p);
+ list_add_tail(p, output);
+ p = next;
+ }
+
+ while (qcount-- && q != input) {
+ struct list_head *next;
+
+ next = q->next;
+ list_del(q);
+ list_add_tail(q, output);
+ q = next;
+ }
+
+ p = q;
+ }
+
+ tmp = input;
+ input = output;
+ output = tmp;
+
+ k *= 2;
+ } while (nmerge > 1);
+
+ list_move_all(head, input);
+}
--
1.6.0.6
------------------------------------------------------------------------------
Stay on top of everything new and different, both inside and
around Java (TM) technology - register by April 22, and save
$200 on the JavaOne (SM) conference, June 2-5, 2009, San Francisco.
300 plus technical and hands-on sessions. Register today.
Use priority code J9JMT32. http://p.sf.net/sfu/p
_______________________________________________
Jatovm-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jatovm-devel