commit b59ce39f9779cf4b1ad423783b6a532f94a8e880
parent 157ecd01d6cc4598ce4b0ec9bd477abbbf41d6c5
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Fri, 9 Jan 2015 16:10:40 +0000
Add cancellation to iterators over avltree(n) and genset(dyn)
Diffstat:
13 files changed, 101 insertions(+), 30 deletions(-)
diff --git a/package/deps.mak b/package/deps.mak
@@ -103,6 +103,7 @@ src/libdatastruct/avlnode_extremenode.o src/libdatastruct/avlnode_extremenode.lo
src/libdatastruct/avlnode_height.o src/libdatastruct/avlnode_height.lo: src/libdatastruct/avlnode_height.c src/include/skalibs/avlnode.h
src/libdatastruct/avlnode_insertnode.o src/libdatastruct/avlnode_insertnode.lo: src/libdatastruct/avlnode_insertnode.c src/libdatastruct/avlnode-internal.h src/include/skalibs/avlnode.h src/include/skalibs/functypes.h
src/libdatastruct/avlnode_iter.o src/libdatastruct/avlnode_iter.lo: src/libdatastruct/avlnode_iter.c src/include/skalibs/avlnode.h
+src/libdatastruct/avlnode_iter_withcancel.o src/libdatastruct/avlnode_iter_withcancel.lo: src/libdatastruct/avlnode_iter_withcancel.c src/include/skalibs/avlnode.h
src/libdatastruct/avlnode_rotate.o src/libdatastruct/avlnode_rotate.lo: src/libdatastruct/avlnode_rotate.c src/libdatastruct/avlnode-internal.h src/include/skalibs/avlnode.h
src/libdatastruct/avlnode_search.o src/libdatastruct/avlnode_search.lo: src/libdatastruct/avlnode_search.c src/include/skalibs/avlnode.h
src/libdatastruct/avlnode_searchnode.o src/libdatastruct/avlnode_searchnode.lo: src/libdatastruct/avlnode_searchnode.c src/libdatastruct/avlnode-internal.h src/include/skalibs/avlnode.h src/include/skalibs/functypes.h
@@ -119,10 +120,12 @@ src/libdatastruct/avltreen_insert.o src/libdatastruct/avltreen_insert.lo: src/li
src/libdatastruct/avltreen_newnode.o src/libdatastruct/avltreen_newnode.lo: src/libdatastruct/avltreen_newnode.c src/include/skalibs/avlnode.h src/include/skalibs/avltreen.h src/include/skalibs/genset.h
src/libdatastruct/genset.o src/libdatastruct/genset.lo: src/libdatastruct/genset.c src/include/skalibs/genset.h
src/libdatastruct/genset_iter.o src/libdatastruct/genset_iter.lo: src/libdatastruct/genset_iter.c src/include/skalibs/bitarray.h src/include/skalibs/functypes.h src/include/skalibs/genset.h
+src/libdatastruct/genset_iter_withcancel.o src/libdatastruct/genset_iter_withcancel.lo: src/libdatastruct/genset_iter_withcancel.c src/include/skalibs/functypes.h src/include/skalibs/genset.h
src/libdatastruct/gensetdyn_delete.o src/libdatastruct/gensetdyn_delete.lo: src/libdatastruct/gensetdyn_delete.c src/include/skalibs/genalloc.h src/include/skalibs/gensetdyn.h
src/libdatastruct/gensetdyn_free.o src/libdatastruct/gensetdyn_free.lo: src/libdatastruct/gensetdyn_free.c src/include/skalibs/genalloc.h src/include/skalibs/gensetdyn.h src/include/skalibs/stralloc.h
src/libdatastruct/gensetdyn_init.o src/libdatastruct/gensetdyn_init.lo: src/libdatastruct/gensetdyn_init.c src/include/skalibs/genalloc.h src/include/skalibs/gensetdyn.h src/include/skalibs/stralloc.h
src/libdatastruct/gensetdyn_iter.o src/libdatastruct/gensetdyn_iter.lo: src/libdatastruct/gensetdyn_iter.c src/include/skalibs/bitarray.h src/include/skalibs/functypes.h src/include/skalibs/gensetdyn.h
+src/libdatastruct/gensetdyn_iter_withcancel.o src/libdatastruct/gensetdyn_iter_withcancel.lo: src/libdatastruct/gensetdyn_iter_withcancel.c src/include/skalibs/functypes.h src/include/skalibs/gensetdyn.h
src/libdatastruct/gensetdyn_new.o src/libdatastruct/gensetdyn_new.lo: src/libdatastruct/gensetdyn_new.c src/include/skalibs/genalloc.h src/include/skalibs/gensetdyn.h
src/libdatastruct/gensetdyn_ready.o src/libdatastruct/gensetdyn_ready.lo: src/libdatastruct/gensetdyn_ready.c src/include/skalibs/genalloc.h src/include/skalibs/gensetdyn.h src/include/skalibs/stralloc.h
src/libdatastruct/gensetdyn_zero.o src/libdatastruct/gensetdyn_zero.lo: src/libdatastruct/gensetdyn_zero.c src/include/skalibs/gensetdyn.h
diff --git a/src/include/skalibs/avlnode.h b/src/include/skalibs/avlnode.h
@@ -39,6 +39,8 @@ extern unsigned int avlnode_insertnode (avlnode *, unsigned int, unsigned int, u
extern unsigned int avlnode_delete (avlnode *, unsigned int, unsigned int *, void const *, dtokfunc_t_ref, cmpfunc_t_ref, void *) ;
#define avlnode_deletenode(s, max, r, i, dtok, f, p) avlnode_delete(s, max, r, (*(dtok))((s)[i].data), dtok, f, p)
-extern int avlnode_iter (avlnode *, unsigned int, unsigned int, avliterfunc_t_ref, void *) ;
+extern unsigned int avlnode_iter_nocancel (avlnode *, unsigned int, unsigned int, unsigned int, avliterfunc_t_ref, void *) ;
+#define avlnode_iter(tree, max, root, f, stuff) (avlnode_iter_nocancel(tree, max, max, root, f, stuff) == (max))
+extern int avlnode_iter_withcancel (avlnode *, unsigned int, unsigned int, avliterfunc_t_ref, avliterfunc_t_ref, void *) ;
#endif
diff --git a/src/include/skalibs/avltree.h b/src/include/skalibs/avltree.h
@@ -51,5 +51,7 @@ extern int avltree_insert (avltree *, unsigned int) ;
extern int avltree_delete (avltree *, void const *) ;
#define avltree_iter(t, f, p) avlnode_iter(avltree_nodes(t), avltree_totalsize(t), avltree_root(t), f, p)
+#define avltree_iter_nocancel(t, cut, f, p) avlnode_iter(avltree_nodes(t), avltree_totalsize(t), cut, avltree_root(t), f, p)
+#define avltree_iter_withcancel(t, f, cancelf, p) avlnode_iter_withcancel(avltree_nodes(t), avltree_totalsize(t), avltree_root(t), f, cancelf, p)
#endif
diff --git a/src/include/skalibs/avltreen.h b/src/include/skalibs/avltreen.h
@@ -50,6 +50,8 @@ extern int avltreen_insert (avltreen *, unsigned int) ;
extern int avltreen_delete (avltreen *, void const *) ;
#define avltreen_iter(t, f, p) avlnode_iter(avltreen_nodes(t), avltreen_totalsize(t), avltreen_root(t), f, p)
+#define avltreen_iter_nocancel(t, cut, f, p) avlnode_iter_nocancel(avltreen_nodes(t), avltreen_totalsize(t), cut, avltreen_root(t), f, p)
+#define avltreen_iter_withcancel(t, f, cancelf, p) avlnode_iter_withcancel(avltreen_nodes(t), avltreen_totalsize(t), avltreen_root(t), f, cancelf, p)
/* avltreeb: everything in one place. Stack or BSS, or heap if you insist */
@@ -83,5 +85,7 @@ extern int avltreen_delete (avltreen *, void const *) ;
#define avltreeb_delete(t, k) avltreen_delete(&(t)->info, k)
#define avltreeb_iter(t, f, p) avlnode_iter(avltreeb_nodes(t), avltreeb_totalsize(t), avltreeb_root(t), f, p)
+#define avltreeb_iter_nocancel(t, cut, f, p) avlnode_iter_nocancel(avltreeb_nodes(t), avltreeb_totalsize(t), cut, avltreeb_root(t), f, p)
+#define avltreeb_iter_withcancel(t, f, cancelf, p) avlnode_iter_withcancel(avltreeb_nodes(t), avltreeb_totalsize(t), avltreeb_root(t), f, cancelf, p)
#endif
diff --git a/src/include/skalibs/genset.h b/src/include/skalibs/genset.h
@@ -23,8 +23,9 @@ extern void genset_init (genset *, void *, unsigned int *, unsigned int, unsigne
extern unsigned int genset_new (genset *) ;
extern int genset_delete (genset *, unsigned int) ;
#define genset_n(g) ((g)->max - (g)->sp)
-extern unsigned int genset_iter (genset *, iterfunc_t_ref, void *) ;
-
+extern unsigned int genset_iter_nocancel (genset *, unsigned int, iterfunc_t_ref, void *) ;
+#define genset_iter(g, f, stuff) genset_iter_nocancel(g, (g)->max, f, stuff)
+extern int genset_iter_withcancel (genset *, iterfunc_t_ref, iterfunc_t_ref, void *) ;
#define GENSETB_TYPE(type, size) struct { type storage[size] ; unsigned int freelist[size] ; genset info ; }
#define GENSETB_init(type, g, size) GENSET_init(&(g)->info, type, (g)->storage, (g)->freelist, size)
diff --git a/src/include/skalibs/gensetdyn.h b/src/include/skalibs/gensetdyn.h
@@ -35,6 +35,8 @@ extern int gensetdyn_delete (gensetdyn *, unsigned int) ;
#define gensetdyn_p(g, i) ((g)->storage.s + (i) * (g)->esize)
#define GENSETDYN_P(type, g, i) ((type *)gensetdyn_p(g, i))
-extern unsigned int gensetdyn_iter (gensetdyn *, iterfunc_t_ref, void *) ;
+extern unsigned int gensetdyn_iter_nocancel (gensetdyn *, unsigned int, iterfunc_t_ref, void *) ;
+#define gensetdyn_iter(g, f, stuff) gensetdyn_iter_nocancel(g, (g)->storage.len, f, stuff)
+extern int gensetdyn_iter_withcancel (gensetdyn *, iterfunc_t_ref, iterfunc_t_ref, void *) ;
#endif
diff --git a/src/libdatastruct/avlnode_delete.c b/src/libdatastruct/avlnode_delete.c
@@ -4,7 +4,7 @@
#include <skalibs/avlnode.h>
#include "avlnode-internal.h"
-unsigned int avlnode_delete (avlnode_ref s, unsigned int max, unsigned int *root, void const *k, dtokfunc_t_ref dtok, cmpfunc_t_ref f, void *p)
+unsigned int avlnode_delete (avlnode *s, unsigned int max, unsigned int *root, void const *k, dtokfunc_t_ref dtok, cmpfunc_t_ref f, void *p)
{
unsigned int stack[AVLNODE_MAXDEPTH] ;
int spin[AVLNODE_MAXDEPTH] ;
diff --git a/src/libdatastruct/avlnode_iter.c b/src/libdatastruct/avlnode_iter.c
@@ -4,23 +4,27 @@
struct avlnode_iter_s
{
- avlnode *s ;
+ avlnode const *s ;
unsigned int max ;
+ unsigned int cut ;
avliterfunc_t_ref f ;
void *p ;
} ;
-static int avlnode_iter_rec (struct avlnode_iter_s const *blah, unsigned int r, unsigned int h)
+static unsigned int avlnode_iter_rec (struct avlnode_iter_s const *blah, unsigned int r, unsigned int h)
{
- return (r < blah->max) ?
- avlnode_iter_rec(blah, blah->s[r].child[0], h+1)
- && (*blah->f)(blah->s[r].data, h, blah->p)
- && avlnode_iter_rec(blah, blah->s[r].child[1], h+1)
- : 1 ;
+ if (r >= blah->max) return blah->max ;
+ {
+ unsigned int res = avlnode_iter_rec(blah, blah->s[r].child[0], h+1) ;
+ if (res != blah->max) return res ;
+ }
+ if (r == blah->cut) return blah->max ;
+ if (!(*blah->f)(blah->s[r].data, h, blah->p)) return r ;
+ return avlnode_iter_rec(blah, blah->s[r].child[1], h+1) ;
}
-int avlnode_iter (avlnode *s, unsigned int max, unsigned int r, avliterfunc_t_ref f, void *p)
+unsigned int avlnode_iter_nocancel (avlnode *s, unsigned int max, unsigned int cut, unsigned int r, avliterfunc_t_ref f, void *p)
{
- struct avlnode_iter_s blah = { s, max, f, p } ;
+ struct avlnode_iter_s blah = { .s = s, .max = max, .cut = cut, .f = f, .p = p } ;
return avlnode_iter_rec(&blah, r, 0) ;
}
diff --git a/src/libdatastruct/avlnode_iter_withcancel.c b/src/libdatastruct/avlnode_iter_withcancel.c
@@ -0,0 +1,17 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/avlnode.h>
+
+int avlnode_iter_withcancel (avlnode *tree, unsigned int max, unsigned int root, avliterfunc_t_ref f, avliterfunc_t_ref cancelf, void *stuff)
+{
+ unsigned int cut = avlnode_iter_nocancel(tree, max, max, root, f, stuff) ;
+ if (cut != max)
+ {
+ int e = errno ;
+ avlnode_iter_nocancel(tree, max, cut, root, cancelf, stuff) ;
+ errno = e ;
+ return 0 ;
+ }
+ return 1 ;
+}
diff --git a/src/libdatastruct/genset_iter.c b/src/libdatastruct/genset_iter.c
@@ -4,16 +4,16 @@
#include <skalibs/functypes.h>
#include <skalibs/genset.h>
-unsigned int genset_iter (genset *g, iterfunc_t_ref f, void *stuff)
+unsigned int genset_iter_nocancel (genset *g, unsigned int n, iterfunc_t_ref f, void *stuff)
{
- unsigned char bits[bitarray_div8(g->max)] ;
- unsigned int i = 0, j = 0, n = 0, m = genset_n(g) ;
- bitarray_setn(bits, 0, g->max) ;
- for (; i < g->sp ; i++) bitarray_clear(bits, g->freelist[i]) ;
- for (i = 0 ; (i < g->max) && (j < m) ; i++) if (bitarray_peek(bits, i))
+ unsigned char bits[bitarray_div8(n)] ;
+ unsigned int i = 0, j = 0, m = genset_n(g) ;
+ bitarray_setn(bits, 0, n) ;
+ for (; i < g->sp ; i++) if (g->freelist[i] < n) bitarray_clear(bits, g->freelist[i]) ;
+ for (i = 0 ; (i < n) && (j < m) ; i++) if (bitarray_peek(bits, i))
{
j++ ;
- if ((*f)(g->storage + i * g->esize, stuff)) n++ ;
+ if (!(*f)(g->storage + i * g->esize, stuff)) break ;
}
- return n ;
+ return i ;
}
diff --git a/src/libdatastruct/genset_iter_withcancel.c b/src/libdatastruct/genset_iter_withcancel.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/functypes.h>
+#include <skalibs/genset.h>
+
+int genset_iter_withcancel (genset *g, iterfunc_t_ref f, iterfunc_t_ref cancelf, void *stuff)
+{
+ unsigned int n = genset_iter(g, f, stuff) ;
+ if (n < g->max)
+ {
+ int e = errno ;
+ genset_iter_nocancel(g, n, cancelf, stuff) ;
+ errno = e ;
+ return 0 ;
+ }
+ return 1 ;
+}
diff --git a/src/libdatastruct/gensetdyn_iter.c b/src/libdatastruct/gensetdyn_iter.c
@@ -4,23 +4,23 @@
#include <skalibs/functypes.h>
#include <skalibs/gensetdyn.h>
-unsigned int gensetdyn_iter (gensetdyn *g, iterfunc_t_ref f, void *stuff)
+unsigned int gensetdyn_iter_nocancel (gensetdyn *g, unsigned int n, iterfunc_t_ref f, void *stuff)
{
/*
XXX: we may be called by a freeing function, so we cannot alloc -
XXX: so pray that the bitarray fits in the stack.
*/
- unsigned char bits[bitarray_div8(g->storage.len)] ;
- unsigned int i = 0, j = 0, n = 0, m = gensetdyn_n(g) ;
+ unsigned char bits[bitarray_div8(n)] ;
+ unsigned int i = 0, j = 0, m = gensetdyn_n(g) ;
register unsigned int *fl = genalloc_s(unsigned int, &g->freelist) ;
register unsigned int sp = genalloc_len(unsigned int, &g->freelist) ;
- bitarray_setn(bits, 0, g->storage.len) ;
+ bitarray_setn(bits, 0, n) ;
- for (; i < sp ; i++) bitarray_clear(bits, fl[i]) ;
- for (i = 0 ; (i < g->storage.len) && (j < m) ; i++) if (bitarray_peek(bits, i))
+ for (; i < sp ; i++) if (fl[i] < n) bitarray_clear(bits, fl[i]) ;
+ for (i = 0 ; (i < n) && (j < m) ; i++) if (bitarray_peek(bits, i))
{
j++ ;
- if ((*f)(gensetdyn_p(g, i), stuff)) n++ ;
+ if (!(*f)(gensetdyn_p(g, i), stuff)) break ;
}
- return n ;
+ return i ;
}
diff --git a/src/libdatastruct/gensetdyn_iter_withcancel.c b/src/libdatastruct/gensetdyn_iter_withcancel.c
@@ -0,0 +1,18 @@
+/* ISC license. */
+
+#include <errno.h>
+#include <skalibs/functypes.h>
+#include <skalibs/gensetdyn.h>
+
+int gensetdyn_iter_withcancel (gensetdyn *g, iterfunc_t_ref f, iterfunc_t_ref cancelf, void *stuff)
+{
+ unsigned int n = gensetdyn_iter(g, f, stuff) ;
+ if (n < g->storage.len)
+ {
+ int e = errno ;
+ gensetdyn_iter_nocancel(g, n, cancelf, stuff) ;
+ errno = e ;
+ return 0 ;
+ }
+ return 1 ;
+}