#include #include "impl.h" typedef struct b_simple_block B_SIMPLE_BLOCK; // va = allocated size of v // vn = number of v[] elements initialized // vc = number of v[0..vn-1] which are non-nil struct b_simple_block { BLOCKFN **v; int va; int vn; int vc; } ; #ifdef DEBUG_BUILD static void trace_dump_bfns(B_SIMPLE_BLOCK *p) { int i; BLOCKFN *bf; aio__trace_append(&p->vn,sizeof(int)); aio__trace_append(&p->vc,sizeof(int)); for (i=0;ivn;i++) { bf = p->v[i]; if (! bf) { aio__trace_append("\0",1); } else if (bf->flags & BFF_DEAD) { aio__trace_append("\1",1); } else { aio__trace_append("\2",1); aio__trace_append(&bf->fn,sizeof(bf->fn)); aio__trace_append(&bf->arg,sizeof(bf->arg)); } } } #else #define trace_dump_bfns(x) do ; while (0) #endif static void *b_simple_init(void) { B_SIMPLE_BLOCK *p; p = malloc(sizeof(B_SIMPLE_BLOCK)); p->v = 0; p->va = 0; p->vn = 0; p->vc = 0; return(p); } static void b_simple_cleanup(void *pv) { B_SIMPLE_BLOCK *p; p = pv; free(p->v); free(p); } static int b_simple_validid(void *pv, int id) { B_SIMPLE_BLOCK *p; if (id < 0) return(0); p = pv; if (id >= p->vn) return(0); if (! p->v[id]) return(0); return(1); } static int b_simple_new(void *pv, BLOCKFN *bf) { B_SIMPLE_BLOCK *p; int i; p = pv; do <"gotslot"> { if (p->vc < p->vn) { for (i=p->vn-1;i>=0;i--) { if (! p->v[i]) break <"gotslot">; } panic("can't find free slot"); return(0); } p->v = realloc(p->v,sizeof(*p->v)*(p->va+=8)); i = p->vn ++; } while (0); p->v[i] = bf; p->vc ++; aio__trace_s("N"); aio__trace_append(&i,sizeof(int)); if (aio__tracing()) trace_dump_bfns(p); return(i); } static void b_simple_remove(void *pv, int id) { B_SIMPLE_BLOCK *p; p = pv; if ((id < 0) || (id > p->vn) || !p->v[id]) { panic("removing invalid id"); return; } p->v[id]->flags |= BFF_DEAD; } static int b_simple_anyblock(void *pv) { return(((B_SIMPLE_BLOCK *)pv)->vc>0); } static void b_simple_iter(AIO_LOOP **lv, int nl, int (*cb)(BLOCKFN *, void *), void *cbarg) { int i; int j; AIO_LOOP *l; B_SIMPLE_BLOCK *p; BLOCKFN *bf; int dead; if ((nl == 1) && aio__tracing()) { aio__trace_s("I"); trace_dump_bfns(lv[0]->bfns); } for (i=nl-1;i>=0;i--) { l = lv[i]; p = l->bfns; for <"nextbfn"> (j=p->vn-1;j>=0;j--) { bf = p->v[j]; if (! bf) continue; do <"dead"> { if (bf->flags & BFF_DEAD) break <"dead">; dead = (*cb)(bf,cbarg); if (dead) break <"dead">; continue <"nextbfn">; } while (0); free(bf); p->v[j] = 0; p->vc --; } } if ((nl == 1) && aio__tracing()) { aio__trace_s("J"); trace_dump_bfns(lv[0]->bfns); } } static int b_simple_getorder(void *pv __attribute__((__unused__)), int id __attribute__((__unused__))) { return(0); } BIMPL aio__bimpl_simple = BIMPL_INIT(b_simple);