#ifndef NSYNC_TESTING_CLOSURE_H_ #define NSYNC_TESTING_CLOSURE_H_ #include "libc/mem/mem.h" /* A run-once, self-freeing closure. */ typedef struct closure_s { void (*f0) (void *); } closure; /* Run the closure *cl, and free it. */ void closure_run (closure *cl); /* Fork a new thread running the closure *cl, which will be freed when the thread exits. */ void closure_fork (closure *cl); /* To create a closure, declare a closure constructor with the right function arguments. For functions taking no arguments, use CLOSURE_DECL_BODY0 (foo) to generate the static routine: static closure *closure_foo (void (*f) (void)); that will return a closure for any function *f that takes no argument. For an 1-argument function, use CLOSURE_DECL_BODY1 (foo, type) to generate the static routine: static closure *closure_foo (void (*f) (type), type x); that will return a closure for any function taking a single argument of the specified type. For an 2-argument function, use CLOSURE_DECL_BODY2 (foo, type0, type1) to generate the static routine: static closure *closure_foo (void (*f) (type0, type1), type0 x0, type1 x1); that will return a closure for any function taking a "type0" argument, and a "type1" argument. And so on, up to 9 arguments. For example, to make closures out of qsort(): // First, just once (per module) define: // static closure *closure_qsort_args ( // void (*f) (void *, size_t, size_t, int (*)(const void *, const void *)) // void *x0, size_t x1, size_t x2, int (*x3)(const void *, const void *)); // by writing: CLOSURE_DECL_BODY4 (qsort_args, void *, size_t, size_t, int (*)(const void *, const void *)) // Second, for each closure to be created, write something like this: closure *cl = closure_qsort_args (array, n_elements, sizeof (array[0]), &elem_cmp); // Then to run (and free) each closure: closure_run (cl); // This is like calling // qsort (array, n_elements, sizeof (array[0]), &elem_cmp); // free (cl); */ /* ------------------------------------------------------------------ */ /* Internal macro details follow. */ #define CLOSURE_S0(x,e) e #define CLOSURE_S1(x,e) x##0 #define CLOSURE_S2(x,e) x##0, x##1 #define CLOSURE_S3(x,e) x##0, x##1, x##2 #define CLOSURE_S4(x,e) x##0, x##1, x##2, x##3 #define CLOSURE_S5(x,e) x##0, x##1, x##2, x##3, x##4 #define CLOSURE_S6(x,e) x##0, x##1, x##2, x##3, x##4, x##5 #define CLOSURE_S7(x,e) x##0, x##1, x##2, x##3, x##4, x##5, x##6 #define CLOSURE_S8(x,e) x##0, x##1, x##2, x##3, x##4, x##5, x##6, x##7 #define CLOSURE_S9(x,e) x##0, x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8 #define CLOSURE_P0(x,y,p,s,t) #define CLOSURE_P1(x,y,p,s,t) p x##0 y##0 t #define CLOSURE_P2(x,y,p,s,t) p x##0 y##0 s x##1 y##1 t #define CLOSURE_P3(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 t #define CLOSURE_P4(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 t #define CLOSURE_P5(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 s x##4 y##4 t #define CLOSURE_P6(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 s x##4 y##4 s \ x##5 y##5 t #define CLOSURE_P7(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 s x##4 y##4 s \ x##5 y##5 s x##6 y##6 t #define CLOSURE_P8(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 s x##4 y##4 s \ x##5 y##5 s x##6 y##6 s x##7 y##7 t #define CLOSURE_P9(x,y,p,s,t) p x##0 y##0 s x##1 y##1 s x##2 y##2 s x##3 y##3 s x##4 y##4 s \ x##5 y##5 s x##6 y##6 s x##7 y##7 s x##8 y##8 t #define CLOSURE_COMMA_ , #define CLOSURE_SEMI_ ; #define CLOSURE_BLANK_ #define CLOSURE_DECL_BODY_N_(name, n) \ struct closure_s_##name { \ void (*f0) (void *); /* must be first; matches closure. */ \ void (*f) (CLOSURE_S##n (closure_t_##name##_,void)); \ CLOSURE_P##n (closure_t_##name##_, a, CLOSURE_BLANK_, \ CLOSURE_SEMI_, CLOSURE_SEMI_) \ }; \ static void closure_f0_##name (void *v) { \ struct closure_s_##name *a = (struct closure_s_##name *) v; \ (*a->f) (CLOSURE_S##n (a->a,CLOSURE_BLANK_)); \ free (a); \ } \ static closure *closure_##name (void (*f) (CLOSURE_S##n (closure_t_##name##_,void)) \ CLOSURE_P##n (closure_t_##name##_, a, CLOSURE_COMMA_, \ CLOSURE_COMMA_, CLOSURE_BLANK_)) { \ struct closure_s_##name *cl = (struct closure_s_##name *) malloc (sizeof (*cl)); \ cl->f0 = &closure_f0_##name; \ cl->f = f; \ CLOSURE_P##n (cl->a, = a, CLOSURE_BLANK_, CLOSURE_SEMI_, CLOSURE_SEMI_) \ return ((closure *) cl); \ } #define CLOSURE_DECL_BODY0(name) \ CLOSURE_DECL_BODY_N_ (name, 0) #define CLOSURE_DECL_BODY1(name, t0) \ typedef t0 closure_t_##name##_0; \ CLOSURE_DECL_BODY_N_ (name, 1) #define CLOSURE_DECL_BODY2(name, t0, t1) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ CLOSURE_DECL_BODY_N_ (name, 2) #define CLOSURE_DECL_BODY3(name, t0, t1, t2) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ CLOSURE_DECL_BODY_N_ (name, 3) #define CLOSURE_DECL_BODY4(name, t0, t1, t2, t3) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ CLOSURE_DECL_BODY_N_ (name, 4) #define CLOSURE_DECL_BODY5(name, t0, t1, t2, t3, t4) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ typedef t4 closure_t_##name##_4; \ CLOSURE_DECL_BODY_N_ (name, 5) #define CLOSURE_DECL_BODY6(name, t0, t1, t2, t3, t4, t5) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ typedef t4 closure_t_##name##_4; \ typedef t5 closure_t_##name##_5; \ CLOSURE_DECL_BODY_N_ (name, 6) #define CLOSURE_DECL_BODY7(name, t0, t1, t2, t3, t4, t5, t6) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ typedef t4 closure_t_##name##_4; \ typedef t5 closure_t_##name##_5; \ typedef t6 closure_t_##name##_6; \ CLOSURE_DECL_BODY_N_ (name, 7) #define CLOSURE_DECL_BODY8(name, t0, t1, t2, t3, t4, t5, t6, t7) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ typedef t4 closure_t_##name##_4; \ typedef t5 closure_t_##name##_5; \ typedef t6 closure_t_##name##_6; \ typedef t7 closure_t_##name##_7; \ CLOSURE_DECL_BODY_N_ (name, 8) #define CLOSURE_DECL_BODY9(name, t0, t1, t2, t3, t4, t5, t6, t7, t8) \ typedef t0 closure_t_##name##_0; \ typedef t1 closure_t_##name##_1; \ typedef t2 closure_t_##name##_2; \ typedef t3 closure_t_##name##_3; \ typedef t4 closure_t_##name##_4; \ typedef t5 closure_t_##name##_5; \ typedef t6 closure_t_##name##_6; \ typedef t7 closure_t_##name##_7; \ typedef t8 closure_t_##name##_8; \ CLOSURE_DECL_BODY_N_ (name, 9) #endif /*NSYNC_TESTING_CLOSURE_H_*/