From 1cae5e22834e299b993e902320012703c9315070 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Wed, 23 Feb 2011 22:18:58 -0800 Subject: [PATCH] Added quicklist, a linked list with better cache characteristics. --- src/build/util.c | 1 + src/util.vcxproj | 2 + src/util.vcxproj.filters | 6 ++ src/util/quicklist.c | 115 +++++++++++++++++++++++++++++++++++++++ src/util/quicklist.h | 35 ++++++++++++ 5 files changed, 159 insertions(+) create mode 100644 src/util/quicklist.c create mode 100644 src/util/quicklist.h diff --git a/src/build/util.c b/src/build/util.c index dfae8d012..c9a6897aa 100644 --- a/src/build/util.c +++ b/src/build/util.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/src/util.vcxproj b/src/util.vcxproj index 6c774d665..b744abb18 100644 --- a/src/util.vcxproj +++ b/src/util.vcxproj @@ -109,6 +109,7 @@ + @@ -145,6 +146,7 @@ + diff --git a/src/util.vcxproj.filters b/src/util.vcxproj.filters index 237444227..6d6e644bf 100644 --- a/src/util.vcxproj.filters +++ b/src/util.vcxproj.filters @@ -107,6 +107,9 @@ Header Files + + Header Files + @@ -199,5 +202,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/src/util/quicklist.c b/src/util/quicklist.c new file mode 100644 index 000000000..729d2ec37 --- /dev/null +++ b/src/util/quicklist.c @@ -0,0 +1,115 @@ +/* +Copyright (c) 2010-2011, Enno Rehling + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#include "quicklist.h" +#include +#include +#include + +#define QL_MAXSIZE 14 /* total struct is 64 bytes */ +#define QL_LIMIT 8 + +typedef struct quicklist { + struct quicklist * next; + int num_elements; + void * elements[QL_MAXSIZE]; +} quicklist; + + +void * ql_get(quicklist * ql, int index) { + return (ql && indexnum_elements)?ql->elements[index]:ql_get(ql->next, index-ql->num_elements); +} + +int ql_length(const quicklist * ql) { + return ql?ql->num_elements+ql_length(ql->next):0; +} + +void ql_push(quicklist ** qlp, void * data) { + quicklist * ql = 0; + while(*qlp && ((*qlp)->next || (*qlp)->num_elements==QL_MAXSIZE)) { + qlp = &(*qlp)->next; + } + if (!*qlp) { + ql = malloc(sizeof(quicklist)); + ql->num_elements = 0; + ql->next = 0; + *qlp = ql; + } else { + ql = *qlp; + } + ql->elements[ql->num_elements++] = data; +} + +int ql_delete(quicklist ** qlp, int index) { + quicklist * ql = *qlp; + if (index<0) return EINVAL; + if (ql && index>=ql->num_elements) { + return ql_delete(&ql->next, index-ql->num_elements); + } else if (ql) { + if (index+1num_elements) { + memmove(ql->elements+index, ql->elements+index+1, (ql->num_elements-index-1)*sizeof(void*)); + } + --ql->num_elements; + if (ql->num_elements==0) { + *qlp = ql->next; + free(ql); + } else if (ql->next && ql->num_elementsnext; + if (ql->num_elements+qn->num_elements>QL_MAXSIZE) { + memcpy(ql->elements+ql->num_elements, qn->elements, sizeof(void*)); + --qn->num_elements; + ++ql->num_elements; + memmove(qn->elements, qn->elements+1, qn->num_elements*sizeof(void*)); + } else { + memcpy(ql->elements+ql->num_elements, qn->elements, qn->num_elements*sizeof(void*)); + ql->num_elements += qn->num_elements; + ql->next = qn->next; + free(qn); + } + } + } + return 0; +} + +int ql_insert(quicklist ** qlp, int index, void * data) { + quicklist * ql = *qlp; + if (ql) { + if (index>=QL_MAXSIZE) { + return ql_insert(&ql->next, index-ql->num_elements, data); + } else if (ql->num_elementselements+index+1, ql->elements+index, (ql->num_elements-index)*sizeof(void*)); + ql->elements[index]=data; + ++ql->num_elements; + } else { + quicklist * qn = malloc(sizeof(quicklist)); + qn->next = ql->next; + ql->next = qn; + qn->num_elements = QL_LIMIT; + ql->num_elements -= QL_LIMIT; + memcpy(qn->elements, ql->elements+ql->num_elements-QL_LIMIT, QL_LIMIT*sizeof(void*)); + if (index<=ql->num_elements) { + return ql_insert(qlp, index, data); + } else { + return ql_insert(&ql->next, index-ql->num_elements, data); + } + } + } else if (index==0) { + ql_push(qlp, data); + } else { + return EINVAL; + } + return 0; +} diff --git a/src/util/quicklist.h b/src/util/quicklist.h new file mode 100644 index 000000000..d77ebcf94 --- /dev/null +++ b/src/util/quicklist.h @@ -0,0 +1,35 @@ +/* +Copyright (c) 2010-2011, Enno Rehling + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +**/ + +#ifndef _QUICKLIST_H +#define _QUICKLIST_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* see http://en.wikipedia.org/wiki/Unrolled_linked_list */ +struct quicklist; +void * ql_get(struct quicklist * ql, int index); +int ql_length(const struct quicklist * ql); +void ql_push(struct quicklist ** qlp, void * data); +int ql_delete(struct quicklist ** qlp, int index); +int ql_insert(struct quicklist ** qlp, int index, void * data); + +#ifdef __cplusplus +} +#endif +#endif