diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2011-06-20 16:54:15 +0930 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2011-06-20 11:18:34 +0200 |
commit | 754c677b0bbf3ea6c7d2a73c93848f1b0d68c91e (patch) | |
tree | 54d99c9f66d5a57bf7f70d53e744a31df18f9e0e /lib/ccan/typesafe_cb/_info | |
parent | a8c3d38bc806c6972d10b6a371de8941da25a9ae (diff) | |
download | samba-754c677b0bbf3ea6c7d2a73c93848f1b0d68c91e.tar.gz samba-754c677b0bbf3ea6c7d2a73c93848f1b0d68c91e.tar.bz2 samba-754c677b0bbf3ea6c7d2a73c93848f1b0d68c91e.zip |
lib: import ccan modules for tdb2
Imported from git://git.ozlabs.org/~ccan/ccan init-1161-g661d41f
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'lib/ccan/typesafe_cb/_info')
-rw-r--r-- | lib/ccan/typesafe_cb/_info | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/ccan/typesafe_cb/_info b/lib/ccan/typesafe_cb/_info new file mode 100644 index 0000000000..4f4570afc9 --- /dev/null +++ b/lib/ccan/typesafe_cb/_info @@ -0,0 +1,151 @@ +#include <stdio.h> +#include <string.h> +#include "config.h" + +/** + * typesafe_cb - macros for safe callbacks. + * + * The basis of the typesafe_cb header is typesafe_cb_cast(): a + * conditional cast macro. If an expression exactly matches a given + * type, it is cast to the target type, otherwise it is left alone. + * + * This allows us to create functions which take a small number of + * specific types, rather than being forced to use a void *. In + * particular, it is useful for creating typesafe callbacks as the + * helpers typesafe_cb(), typesafe_cb_preargs() and + * typesafe_cb_postargs() demonstrate. + * + * The standard way of passing arguments to callback functions in C is + * to use a void pointer, which the callback then casts back to the + * expected type. This unfortunately subverts the type checking the + * compiler would perform if it were a direct call. Here's an example: + * + * static void my_callback(void *_obj) + * { + * struct obj *obj = _obj; + * ... + * } + * ... + * register_callback(my_callback, &my_obj); + * + * If we wanted to use the natural type for my_callback (ie. "void + * my_callback(struct obj *obj)"), we could make register_callback() + * take a void * as its first argument, but this would subvert all + * type checking. We really want register_callback() to accept only + * the exactly correct function type to match the argument, or a + * function which takes a void *. + * + * This is where typesafe_cb() comes in: it uses typesafe_cb_cast() to + * cast the callback function if it matches the argument type: + * + * void _register_callback(void (*cb)(void *arg), void *arg); + * #define register_callback(cb, arg) \ + * _register_callback(typesafe_cb(void, void *, (cb), (arg)), \ + * (arg)) + * + * On compilers which don't support the extensions required + * typesafe_cb_cast() and friend become an unconditional cast, so your + * code will compile but you won't get type checking. + * + * Example: + * #include <ccan/typesafe_cb/typesafe_cb.h> + * #include <stdlib.h> + * #include <stdio.h> + * + * // Generic callback infrastructure. + * struct callback { + * struct callback *next; + * int value; + * int (*callback)(int value, void *arg); + * void *arg; + * }; + * static struct callback *callbacks; + * + * static void _register_callback(int value, int (*cb)(int, void *), + * void *arg) + * { + * struct callback *new = malloc(sizeof(*new)); + * new->next = callbacks; + * new->value = value; + * new->callback = cb; + * new->arg = arg; + * callbacks = new; + * } + * #define register_callback(value, cb, arg) \ + * _register_callback(value, \ + * typesafe_cb_preargs(int, void *, \ + * (cb), (arg), int),\ + * (arg)) + * + * static struct callback *find_callback(int value) + * { + * struct callback *i; + * + * for (i = callbacks; i; i = i->next) + * if (i->value == value) + * return i; + * return NULL; + * } + * + * // Define several silly callbacks. Note they don't use void *! + * #define DEF_CALLBACK(name, op) \ + * static int name(int val, int *arg) \ + * { \ + * printf("%s", #op); \ + * return val op *arg; \ + * } + * DEF_CALLBACK(multiply, *); + * DEF_CALLBACK(add, +); + * DEF_CALLBACK(divide, /); + * DEF_CALLBACK(sub, -); + * DEF_CALLBACK(or, |); + * DEF_CALLBACK(and, &); + * DEF_CALLBACK(xor, ^); + * DEF_CALLBACK(assign, =); + * + * // Silly game to find the longest chain of values. + * int main(int argc, char *argv[]) + * { + * int i, run = 1, num = argv[1] ? atoi(argv[1]) : 0; + * + * for (i = 1; i < 1024;) { + * // Since run is an int, compiler checks "add" does too. + * register_callback(i++, add, &run); + * register_callback(i++, divide, &run); + * register_callback(i++, sub, &run); + * register_callback(i++, multiply, &run); + * register_callback(i++, or, &run); + * register_callback(i++, and, &run); + * register_callback(i++, xor, &run); + * register_callback(i++, assign, &run); + * } + * + * printf("%i ", num); + * while (run < 56) { + * struct callback *cb = find_callback(num % i); + * if (!cb) { + * printf("-> STOP\n"); + * return 1; + * } + * num = cb->callback(num, cb->arg); + * printf("->%i ", num); + * run++; + * } + * printf("-> Winner!\n"); + * return 0; + * } + * + * License: LGPL (2 or any later version) + * Author: Rusty Russell <rusty@rustcorp.com.au> + */ +int main(int argc, char *argv[]) +{ + if (argc != 2) + return 1; + + if (strcmp(argv[1], "depends") == 0) { + return 0; + } + + return 1; +} |