From: Not Zed Date: Tue, 23 Jul 2024 04:26:49 +0000 (+0930) Subject: Change ez_node to use anonymous unions/structs for convenience. X-Git-Url: https://code.zedzone.au/cvs?a=commitdiff_plain;h=13779f4e54c07c3edf3db3934db8a7cbb33483a7;p=libeze Change ez_node to use anonymous unions/structs for convenience. --- diff --git a/ez-list.h b/ez-list.h index 5e67e6f..d3494eb 100644 --- a/ez-list.h +++ b/ez-list.h @@ -23,7 +23,7 @@ /** * ez-list is a low-level double-linked list implementation that works - * without memory allocation. + * without memory allocation. * * o Adding to or removing from either end is an O(1) operation. * o Removing any given node is an O(1) operation. @@ -94,9 +94,9 @@ struct ez_list { /** * Initialise a list at runtime. - * + * */ -static __inline__ void ez_list_init(struct ez_list *l) { +static __inline__ void ez_list_init(struct ez_list * __restrict l) { l->head = (struct ez_node *)&l->tail; l->tail = (struct ez_node *)0L; l->tail_pred = (struct ez_node *)&l->head; @@ -105,12 +105,12 @@ static __inline__ void ez_list_init(struct ez_list *l) { /** * Add a node to the head of the list. */ -static __inline__ void ez_list_addhead(struct ez_list *l, void *np) { +static __inline__ void ez_list_addhead(struct ez_list * __restrict l, void *np) { struct ez_node *n = np, *head = l->head; - n->u.list.succ = head; - n->u.list.pred = (struct ez_node *)&l->head; - head->u.list.pred = n; + n->succ = head; + n->pred = (struct ez_node *)&l->head; + head->pred = n; l->head = n; } @@ -120,9 +120,9 @@ static __inline__ void ez_list_addhead(struct ez_list *l, void *np) { static __inline__ void ez_list_addtail(struct ez_list *l, void *np) { struct ez_node *n = np, *tail_pred = l->tail_pred; - n->u.list.pred = tail_pred; - n->u.list.succ = (struct ez_node *)&l->tail; - tail_pred->u.list.succ = n; + n->pred = tail_pred; + n->succ = (struct ez_node *)&l->tail; + tail_pred->succ = n; l->tail_pred = n; } @@ -134,11 +134,11 @@ static __inline__ void ez_list_addtail(struct ez_list *l, void *np) { * This performs a software memory barrier after * write do workaround aliasing issues with gcc. */ -static __inline__ void ez_node_remove(void *np) { - struct ez_node *n = np, *pred = n->u.list.pred, *succ = n->u.list.succ; - - pred->u.list.succ = succ; - succ->u.list.pred = pred; +static __inline__ void ez_node_remove(void * __restrict np) { + struct ez_node *n = np, *pred = n->pred, *succ = n->succ; + + pred->succ = succ; + succ->pred = pred; } /** @@ -146,12 +146,12 @@ static __inline__ void ez_node_remove(void *np) { * * @return the head node, or NULL if the list is empty. */ -static __inline__ void *ez_list_remhead(struct ez_list *l) { +static __inline__ void *ez_list_remhead(struct ez_list * __restrict l) { struct ez_node *n = l->head; - struct ez_node *s = n->u.list.succ; + struct ez_node *s = n->succ; if (s) { - s->u.list.pred = (struct ez_node *)&l->head; + s->pred = (struct ez_node *)&l->head; l->head = s; return n; } else @@ -163,12 +163,12 @@ static __inline__ void *ez_list_remhead(struct ez_list *l) { * * @return the tail node, or NULL if the list is empty. */ -static __inline__ void *ez_list_remtail(struct ez_list *l) { +static __inline__ void *ez_list_remtail(struct ez_list * __restrict l) { struct ez_node *n = l->tail_pred; - struct ez_node *p = n->u.list.pred; + struct ez_node *p = n->pred; if (p) { - p->u.list.succ = (struct ez_node *)&l->tail; + p->succ = (struct ez_node *)&l->tail; l->tail_pred = p; return n; } else @@ -182,15 +182,15 @@ static __inline__ void *ez_list_remtail(struct ez_list *l) { * @param n node to insert. * @param p node that is already present in list, or NULL (insert after head). */ -static __inline__ void ez_list_insert_after(struct ez_list *l, void *n, void *p) { +static __inline__ void ez_list_insert_after(struct ez_list * __restrict l, void *n, void *p) { struct ez_node *nn = n; struct ez_node *pp = p ? p : (struct ez_node *)&l->head; - struct ez_node *succ = pp->u.list.succ; + struct ez_node *succ = pp->succ; - nn->u.list.succ = succ; - nn->u.list.pred = pp; - succ->u.list.pred = nn; - pp->u.list.succ = nn; + nn->succ = succ; + nn->pred = pp; + succ->pred = nn; + pp->succ = nn; } /** @@ -200,15 +200,15 @@ static __inline__ void ez_list_insert_after(struct ez_list *l, void *n, void *p) * @param n node to insert. * @param p node that is already present in list, or NULL (insert before tail). */ -static __inline__ void ez_list_insert(struct ez_list *l, void *n, void *p) { +static __inline__ void ez_list_insert(struct ez_list * __restrict l, void *n, void *p) { struct ez_node *nn = n; struct ez_node *pp = p ? p : (struct ez_node *)&l->tail; - struct ez_node *pred = pp->u.list.pred; - - nn->u.list.succ = pp; - nn->u.list.pred = pred; - pred->u.list.succ = nn; - pp->u.list.pred = nn; + struct ez_node *pred = pp->pred; + + nn->succ = pp; + nn->pred = pred; + pred->succ = nn; + pp->pred = nn; } /** @@ -217,11 +217,11 @@ static __inline__ void ez_list_insert(struct ez_list *l, void *n, void *p) { * This is an O(n) operation, use ez_list_empty() to check for empty * lists. */ -static __inline__ int ez_list_size(struct ez_list *l) { +static __inline__ int ez_list_size(struct ez_list * __restrict l) { struct ez_node *w, *n; int size = 0; - for (w = l->head, n = w->u.list.succ; n; w = n, n = n->u.list.succ) + for (w = l->head, n = w->succ; n; w = n, n = n->succ) size += 1; return size; @@ -232,21 +232,21 @@ static __inline__ int ez_list_size(struct ez_list *l) { * * @param returns true (1) if the list is empty. */ -static __inline__ int ez_list_empty(struct ez_list *l) { +static __inline__ int ez_list_empty(struct ez_list * __restrict l) { return l->tail_pred == (struct ez_node *)l; } /** * Retrieve the successor to the head node (the first user node). */ -static __inline__ void *ez_list_head(struct ez_list *l) { +static __inline__ void *ez_list_head(struct ez_list * __restrict l) { return (void *)l->head; } /** * Retrieve the predecessor of the tail node (the last user node). */ -static __inline__ void *ez_list_tail(struct ez_list *l) { +static __inline__ void *ez_list_tail(struct ez_list * __restrict l) { return (void *)l->tail_pred; } @@ -262,5 +262,5 @@ static void ez_list_insert(struct ez_list *l, void *n, void *p) __attribute__ (( static int ez_list_empty(struct ez_list *l) __attribute__ ((always_inline)); static void *ez_list_head(struct ez_list *l) __attribute__ ((always_inline)); static void *ez_list_tail(struct ez_list *l) __attribute__ ((always_inline)); - + #endif diff --git a/ez-node.h b/ez-node.h index 7e3a7d5..9664290 100644 --- a/ez-node.h +++ b/ez-node.h @@ -39,15 +39,15 @@ struct ez_node { struct { struct ez_node * volatile succ; struct ez_node * volatile pred; - } list; + }; struct { intptr_t link[2]; - } tree; + }; struct { struct ez_node *next; unsigned int hash; - } set; - } u; + }; + }; }; /** @@ -70,7 +70,7 @@ typedef void (*ez_free_fn)(void *); * == NULL. */ static __inline__ void *ez_node_succ(void *n) { - return (void *)((struct ez_node *)n)->u.list.succ; + return (void *)((struct ez_node *)n)->succ; } /** @@ -80,42 +80,42 @@ static __inline__ void *ez_node_succ(void *n) { * == NULL. */ static __inline__ void *ez_node_pred(void *n) { - return (void *)((struct ez_node *)n)->u.list.pred; + return (void *)((struct ez_node *)n)->pred; } /** * Retrieve the left child tree node. */ static __inline__ void *ez_node_left(void *node) { - return (void *)(((struct ez_node *)node)->u.tree.link[0] & ~3); + return (void *)(((struct ez_node *)node)->link[0] & ~3); } /** * Retrieve the right child tree node. */ static __inline__ void *ez_node_right(void *node) { - return (void *)(((struct ez_node *)node)->u.tree.link[1] & ~3); + return (void *)(((struct ez_node *)node)->link[1] & ~3); } /** * Retrieve either the left or right child node. */ static __inline__ void *ez_node_link(void *node, enum ez_node_link_t i) { - return (void *)(((struct ez_node *)node)->u.tree.link[i] & ~3); + return (void *)(((struct ez_node *)node)->link[i] & ~3); } /** * Retrieve the next set hash chain bucket. */ static __inline__ void *ez_node_next(void *node) { - return ((struct ez_node *)node)->u.set.next; + return ((struct ez_node *)node)->next; } /** * Retrieve the set hash bucket hash. */ static __inline__ unsigned int ez_node_hash(void *node) { - return ((struct ez_node *)node)->u.set.hash; + return ((struct ez_node *)node)->hash; } static void *ez_node_succ(void *n) __attribute__ ((always_inline)); diff --git a/ez-set.c b/ez-set.c index 0705bef..762eca9 100644 --- a/ez-set.c +++ b/ez-set.c @@ -48,9 +48,9 @@ static ez_node *set_lookup(ez_set *h, const ez_node *key, unsigned int hash, ez_ ez_node *scan = h->table[idx]; ez_node *p = (ez_node *)&h->table[idx]; - while (scan && !(hash == scan->u.set.hash && h->equals(key, scan))) { + while (scan && !(hash == scan->hash && h->equals(key, scan))) { p = scan; - scan = scan->u.set.next; + scan = scan->next; } *pp = p; @@ -76,10 +76,10 @@ static void set_rehash(ez_set *h, int newsize) { ez_node *e = h->table[i]; while (e) { - ez_node *n = e->u.set.next; - unsigned int nidx = e->u.set.hash & mask; + ez_node *n = e->next; + unsigned int nidx = e->hash & mask; - e->u.set.next = table[nidx]; + e->next = table[nidx]; table[nidx] = e; e = n; @@ -155,17 +155,17 @@ void *ez_set_put(ez_set *h, void *ep) { } // Entries are only ever hashed once, here. - e->u.set.hash = h->hash(e); - scan = set_lookup(h, e, e->u.set.hash, &p); + e->hash = h->hash(e); + scan = set_lookup(h, e, e->hash, &p); // insert new node, possibly unlinking old one - p->u.set.next = e; + p->next = e; if (scan) { // link old node tail - e->u.set.next = scan->u.set.next; + e->next = scan->next; } else { // new node added - e->u.set.next = NULL; + e->next = NULL; h->count += 1; if (h->count > h->mask) set_rehash(h, (h->mask+1) * 2); @@ -197,7 +197,7 @@ void *ez_set_remove(ez_set *h, const void *ep) { scan = set_lookup(h, e, hash, &p); if (scan) { // unlink old node - p->u.set.next = scan->u.set.next; + p->next = scan->next; h->count -= 1; if (h->mask > 15 && h->count*2 < h->mask) set_rehash(h, (h->mask+1)>>1); @@ -222,7 +222,7 @@ void *ez_set_scan_next(ez_set_scan *scan) { if (scan->e) { // advance e and p scan->p = scan->e; - scan->e = scan->e->u.set.next; + scan->e = scan->e->next; if (!scan->e) return scan_next_chain(scan->set, scan, scan->idx); @@ -234,7 +234,7 @@ void *ez_set_scan_next(ez_set_scan *scan) { void *ez_set_scan_remove(ez_set_scan *scan) { if (scan->e) { // unlink e and advance but don't change p - scan->p->u.set.next = scan->e = scan->e->u.set.next; + scan->p->next = scan->e = scan->e->next; scan->set->count -= 1; if (!scan->e) diff --git a/ez-tree.c b/ez-tree.c index 5ebb2af..6fcfb08 100644 --- a/ez-tree.c +++ b/ez-tree.c @@ -80,20 +80,20 @@ static void *fail_depth(void) { } static __inline__ int node_balance(struct ez_node *n) { - int i = n->u.tree.link[0]; + int i = n->link[0]; return i << 30 >> 30; } static __inline__ void node_set_balance(struct ez_node *node, int balance) { - node->u.tree.link[0] = (node->u.tree.link[0] & ~3) | (balance & 3); + node->link[0] = (node->link[0] & ~3) | (balance & 3); } static __inline__ void *node_link(struct ez_node *n, int i) { - return (void *)(n->u.tree.link[i] & ~3); + return (void *)(n->link[i] & ~3); } static __inline__ void node_set_link(struct ez_node *n, int i, struct ez_node *link) { - n->u.tree.link[i] = (n->u.tree.link[i] & 3) | (intptr_t)link; + n->link[i] = (n->link[i] & 3) | (intptr_t)link; } /** @@ -229,7 +229,7 @@ static void node_remove(struct ez_tree_scan_info *stack, struct ez_tree_scan_inf si -= 1; } - stack[0].node->u.tree.link[0] -= 1; + stack[0].node->link[0] -= 1; } /** @@ -251,15 +251,15 @@ static void tree_free(ez_tree *tree, struct ez_node *n, ez_free_fn node_free) { /* ********************************************************************** */ void ez_tree_init(struct ez_tree *tree, ez_cmp_fn node_cmp) { - tree->root.u.tree.link[0] = 0; - tree->root.u.tree.link[1] = 0; + tree->root.link[0] = 0; + tree->root.link[1] = 0; tree->node_cmp = node_cmp; } void ez_tree_clear(ez_tree *tree, ez_free_fn node_free) { tree_free(tree, ez_tree_root(tree), node_free); - tree->root.u.tree.link[0] = 0; - tree->root.u.tree.link[1] = 0; + tree->root.link[0] = 0; + tree->root.link[1] = 0; } void *ez_tree_get(ez_tree *tree, const void *node) { @@ -285,12 +285,12 @@ void *ez_tree_put(ez_tree *tree, void *node) { struct ez_tree_scan_info *sp = stack, *se = sp + EZ_TREE_MAX_DEPTH - 1; ez_cmp_fn node_cmp = tree->node_cmp; - k->u.tree.link[0] = BALANCE0; // balance=0 + k->link[0] = BALANCE0; // balance=0 node_set_link(k, 1, 0); - if (!tree->root.u.tree.link[1]) { - tree->root.u.tree.link[1] = (intptr_t)k; - tree->root.u.tree.link[0] += 1; + if (!tree->root.link[1]) { + tree->root.link[1] = (intptr_t)k; + tree->root.link[0] += 1; return NULL; } @@ -321,7 +321,7 @@ void *ez_tree_put(ez_tree *tree, void *node) { // Insert new node node_set_link(p, cmp > 0, k); - tree->root.u.tree.link[0] += 1; + tree->root.link[0] += 1; *sp = (struct ez_tree_scan_info){ k, 0 }; // Fix balance factors between s and q diff --git a/ez-tree.h b/ez-tree.h index 83c9b7a..c2bcac9 100644 --- a/ez-tree.h +++ b/ez-tree.h @@ -40,7 +40,7 @@ struct ez_tree { * * struct ez_tree tree = EZ_INIT_TREE(tree, cmp); */ -#define EZ_INIT_TREE(t, cmp) { .root.u.tree.link[0] = 0, .root.u.tree.link[1] = 0, .node_cmp = cmp } +#define EZ_INIT_TREE(t, cmp) { .root.link[0] = 0, .root.link[1] = 0, .node_cmp = cmp } typedef struct ez_tree_scan ez_tree_scan; @@ -85,21 +85,21 @@ void ez_tree_init(struct ez_tree *tree, ez_cmp_fn cmp); */ static __inline__ int ez_tree_size(ez_tree *tree) { // well if it's good enough for Knuth. - return tree->root.u.tree.link[0]; + return tree->root.link[0]; } /** * Retrieve the root node of the tree. */ static __inline__ void *ez_tree_root(ez_tree *tree) { - return (void *)tree->root.u.tree.link[1]; + return (void *)tree->root.link[1]; } /** * Determine if the tree is empty. */ static __inline__ int ez_tree_empty(ez_tree *tree) { - return !tree->root.u.tree.link[1]; + return !tree->root.link[1]; } /** diff --git a/test-tree.c b/test-tree.c index 030937b..352174d 100644 --- a/test-tree.c +++ b/test-tree.c @@ -31,7 +31,7 @@ static int node_cmp(const void *a, const void *b) { static __inline__ int node_balance(struct ez_node *n) __attribute__((always_inline)); static __inline__ int node_balance(struct ez_node *n) { - int i = n->u.tree.link[0]; + int i = n->link[0]; return i << 30 >> 30; }