rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit 54d4952c453b3fc9ee46242935dd62fe86ac92ff
parent 064b0e4c74ab1e9585fc2a67e1e61e4571c9861f
Author: vaplv <vaplv@free.fr>
Date:   Sat,  8 Feb 2014 16:57:33 +0100

Drastically change the signal API

Diffstat:
Msrc/rsys.h | 23+++++++++++++++++++++++
Msrc/signal.h | 96+++++++++++++++++++++++++++++++++++++------------------------------------------
Msrc/test_signal.c | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
3 files changed, 146 insertions(+), 87 deletions(-)

diff --git a/src/rsys.h b/src/rsys.h @@ -150,6 +150,29 @@ #endif /******************************************************************************* + * Variadic macros + ******************************************************************************/ +#define ARG0() +#define ARG1(A) +#define ARG2(A, B) +#define ARG3(A, B, C) +#define ARG4(A, B, C, D) +#define ARG5(A, B, C, D, E) + +#define LIST_ARG0() +#define LIST_ARG1(A) A +#define LIST_ARG2(A, B) A, B +#define LIST_ARG3(A, B, C) A, B, C +#define LIST_ARG4(A, B, C, D) A, B, C, D +#define LIST_ARG5(A, B, C, D, E) A, B, C, D, E +#define COMMA_ARG0() +#define COMMA_ARG1(A) , +#define COMMA_ARG2(A, B) , +#define COMMA_ARG3(A, B, C) , +#define COMMA_ARG4(A, B, C, D) , +#define COMMA_ARG5(A, B, C, D, E) , + +/******************************************************************************* * Miscellaneous ******************************************************************************/ #define BIT(Num) (1 << (Num)) diff --git a/src/signal.h b/src/signal.h @@ -4,65 +4,59 @@ #include "list.h" #include "rsys.h" -/****************************************************************************** +/******************************************************************************* * Simple callback data structure ******************************************************************************/ -struct callback { - struct list_node node; - void (*func)(void* args, void* data); - void* data; -}; - -static FINLINE void -callback_init(struct callback* clbk) -{ - ASSERT(clbk); - list_init(&clbk->node); -} - -static FINLINE void -callback_setup(struct callback* clbk, void (*func)(void*, void*), void* data) -{ - ASSERT(clbk); - clbk->func = func; - clbk->data = data; -} - -static FINLINE void -callback_disconnect(struct callback* clbk) -{ - ASSERT(clbk); - list_del(&clbk->node); -} +/* Declare a the callback data structure named `Type'. Its function arguments + * are `Args' and a void pointer toward its user defined data */ +#define CLBK(Type, Args) \ + typedef struct \ + { \ + struct list_node node; \ + void (*func)(LIST_##Args COMMA_##Args void* data ); \ + void* data; /* Data attached to the callback */ \ + } Type + +/* Initialise the callback data structure. Must be called before any callback + * operation */ +#define CLBK_INIT(Clbk) \ + { \ + list_init(&(Clbk)->node); \ + (Clbk)->func = NULL; \ + (Clbk)->data = NULL; \ + } (void)0 + +/* Set the callback function and user defined data */ +#define CLBK_SETUP(Clbk, Func, Data) (Clbk)->func = Func, (Clbk)->data = Data + +/* Disconnect the callback from the signal from which it may be attached */ +#define CLBK_DISCONNECT(Clbk) list_del(&(Clbk)->node) /****************************************************************************** * Minimalist signal data structure ******************************************************************************/ typedef struct list_node signal_T; -static FINLINE void -signal_init(signal_T* signal) -{ - ASSERT(signal); - list_init(signal); -} - -static FINLINE void -signal_connect_callback(signal_T* signal, struct callback* clbk) -{ - ASSERT(signal && clbk); - list_add(signal, &clbk->node); -} - -static FINLINE void -signal_invoke(signal_T* signal, void* args) -{ - struct list_node* pos = NULL; - LIST_FOR_EACH(pos, signal) { - struct callback* clbk = CONTAINER_OF(pos, struct callback, node); - clbk->func(args, clbk->data); - } -} +/* Initialise the signal. Must be called before any signal operation */ +#define SIG_INIT(Sig) list_init(Sig) + +/* Attach the callback to the signal. If it was already attached, Clbk is + * firstly disconnected from the previous signal before its connection to Sig */ +#define SIG_CONNECT_CLBK(Sig, Clbk) \ + is_list_empty(&(Clbk)->node) \ + ? list_add((Sig), &(Clbk)->node) \ + : list_move(&(Clbk)->node, (Sig)) + +/* Invoke the callback attached to `Sig' with the argument `Args' */ +#define SIG_BROADCAST(Sig, ClbkType, Args) \ + { \ + struct list_node *pos, *tmp; \ + LIST_FOR_EACH_SAFE(pos, tmp, (Sig)) { \ + ClbkType* clbk = CONTAINER_OF(pos, ClbkType, node); \ + ASSERT(clbk->func); \ + clbk->func(LIST_##Args COMMA_##Args clbk->data); \ + } \ + } (void)0 #endif /* SIGNAL_H */ diff --git a/src/test_signal.c b/src/test_signal.c @@ -10,107 +10,149 @@ struct ctxt { enum test_signal { SIG0, SIG1, + SIG2, + SIG3, SIGNALS_COUNT }; static void -sig0_func1(void* arg, void* data) +sig0_func1(struct ctxt* ctxt, void* data) { CHECK(data, NULL); - ((struct ctxt*)arg)->sig0_func1_invoked = 1; + ctxt->sig0_func1_invoked = 1; } static void -sig0_func2(void* arg, void* data) +sig0_func2(struct ctxt* ctxt, void* data) { NCHECK(data, NULL); - ((struct ctxt*)arg)->sig0_func2_sum += *((int*)data); + ctxt->sig0_func2_sum += *((int*)data); } static void -sig1_func(void* arg, void* data) +sig1_func(struct ctxt* ctxt, void* data) { NCHECK(data, NULL); - ((struct ctxt*)arg)->sig1_func_sum += *(int*)data; + ctxt->sig1_func_sum += *(int*)data; +} + +static void +sig2_func( void* data ) +{ + NCHECK(data, NULL); + *(uint32_t*)data = 0xDECAFBAD; +} + +static void +sig3_func(int i, float f, char c, void* data) +{ + NCHECK(data, NULL); + CHECK(i, 3); + CHECK(f, 3.14159f); + CHECK(c, 'a'); + *(uint32_t*)data = 0xDECAFBAD; } int main(int argc, char** argv) { signal_T signals[SIGNALS_COUNT]; + + CLBK(clbk_T, ARG1(struct ctxt*)); + CLBK(clbk2_T, ARG0()); + CLBK(clbk3_T, ARG3(int, float, char)); + struct ctxt ctxt; - struct callback clbk0_a; - struct callback clbk0_b; - struct callback clbk0_c; - struct callback clbk1_a; - struct callback clbk1_b; + clbk_T clbk0_a; + clbk_T clbk0_b; + clbk_T clbk0_c; + clbk_T clbk1_a; + clbk_T clbk1_b; + clbk2_T clbk2; + clbk3_T clbk3; int i = 0; int array[] = { 12, -1, 2, 1 }; + uint32_t clbk_data = 0; (void)argc, (void)argv; - FOR_EACH(i, 0, SIGNALS_COUNT) - signal_init(&signals[i]); + FOR_EACH(i, 0, SIGNALS_COUNT) + SIG_INIT(&signals[i]); - callback_init(&clbk0_a); - callback_init(&clbk0_b); - callback_init(&clbk0_c); - callback_init(&clbk1_a); - callback_init(&clbk1_b); - callback_setup(&clbk0_a, sig0_func1, NULL); - callback_setup(&clbk0_b, sig0_func2, array + 0); - callback_setup(&clbk0_c, sig0_func2, array + 1); - callback_setup(&clbk1_a, sig1_func, array + 2); - callback_setup(&clbk1_b, sig1_func, array + 3); + CLBK_INIT(&clbk0_a); + CLBK_INIT(&clbk0_b); + CLBK_INIT(&clbk0_c); + CLBK_INIT(&clbk1_a); + CLBK_INIT(&clbk1_b); + CLBK_SETUP(&clbk0_a, sig0_func1, NULL); + CLBK_SETUP(&clbk0_b, sig0_func2, array + 0); + CLBK_SETUP(&clbk0_c, sig0_func2, array + 1); + CLBK_SETUP(&clbk1_a, sig1_func, array + 2); + CLBK_SETUP(&clbk1_b, sig1_func, array + 3); ctxt.sig0_func1_invoked = 0; ctxt.sig0_func2_sum = 0; ctxt.sig1_func_sum = 0; - signal_invoke(&signals[SIG0], &ctxt); + SIG_BROADCAST(&signals[SIG0], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 0); CHECK(ctxt.sig0_func2_sum, 0); CHECK(ctxt.sig1_func_sum, 0); - signal_invoke(&signals[SIG1], &ctxt); + SIG_BROADCAST(&signals[SIG1], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 0); CHECK(ctxt.sig0_func2_sum, 0); CHECK(ctxt.sig1_func_sum, 0); - signal_connect_callback(&signals[SIG0], &clbk0_a); - signal_connect_callback(&signals[SIG0], &clbk0_b); - signal_connect_callback(&signals[SIG0], &clbk0_c); - signal_invoke(&signals[SIG0], &ctxt); + SIG_CONNECT_CLBK(&signals[SIG0], &clbk0_a); + SIG_CONNECT_CLBK(&signals[SIG0], &clbk0_b); + SIG_CONNECT_CLBK(&signals[SIG0], &clbk0_c); + SIG_BROADCAST(&signals[SIG0], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 1); CHECK(ctxt.sig0_func2_sum, 11); CHECK(ctxt.sig1_func_sum, 0); - callback_disconnect(&clbk0_c); + CLBK_DISCONNECT(&clbk0_c); ctxt.sig0_func1_invoked = 0; ctxt.sig0_func2_sum = 0; ctxt.sig1_func_sum = 0; - signal_invoke(&signals[SIG0], &ctxt); + SIG_BROADCAST(&signals[SIG0], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 1); CHECK(ctxt.sig0_func2_sum, 12); CHECK(ctxt.sig1_func_sum, 0); - signal_connect_callback(&signals[SIG1], &clbk1_a); - signal_invoke(&signals[SIG0], &ctxt); + SIG_CONNECT_CLBK(&signals[SIG1], &clbk1_a); + SIG_BROADCAST(&signals[SIG0], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 1); CHECK(ctxt.sig0_func2_sum, 24); CHECK(ctxt.sig1_func_sum, 0); - signal_invoke(&signals[SIG1], &ctxt); + SIG_BROADCAST(&signals[SIG1], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 1); CHECK(ctxt.sig0_func2_sum, 24); CHECK(ctxt.sig1_func_sum, 2); - signal_connect_callback(&signals[SIG1], &clbk1_b); - signal_invoke(&signals[SIG1], &ctxt); + SIG_CONNECT_CLBK(&signals[SIG1], &clbk1_b); + SIG_BROADCAST(&signals[SIG1], clbk_T, ARG1(&ctxt)); CHECK(ctxt.sig0_func1_invoked, 1); CHECK(ctxt.sig0_func2_sum, 24); CHECK(ctxt.sig1_func_sum, 5); + CLBK_INIT(&clbk2); + CLBK_SETUP(&clbk2, sig2_func, &clbk_data); + SIG_CONNECT_CLBK(&signals[SIG2], &clbk2); + CHECK(clbk_data, 0); + SIG_BROADCAST(&signals[SIG2], clbk2_T, ARG0()); + CHECK(clbk_data, 0xDECAFBAD); + CLBK_DISCONNECT(&clbk2); + + CLBK_INIT(&clbk3); + CLBK_SETUP(&clbk3, &sig3_func, &clbk_data); + SIG_CONNECT_CLBK(&signals[SIG3], &clbk3); + clbk_data = 0; + SIG_BROADCAST(&signals[SIG3], clbk3_T, ARG3(3, 3.14159f, 'a')); + CHECK(clbk_data, 0xDECAFBAD); + CHECK(MEM_ALLOCATED_SIZE(&mem_default_allocator), 0); return 0;