commit 54d4952c453b3fc9ee46242935dd62fe86ac92ff
parent 064b0e4c74ab1e9585fc2a67e1e61e4571c9861f
Author: vaplv <vaplv@free.fr>
Date: Sat, 8 Feb 2014 16:57:33 +0100
Drastically change the signal API
Diffstat:
| M | src/rsys.h | | | 23 | +++++++++++++++++++++++ |
| M | src/signal.h | | | 96 | +++++++++++++++++++++++++++++++++++++------------------------------------------ |
| M | src/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;