Messages in this thread Patch in this message | | | From | Rusty Russell <> | Subject | [PATCH 2/6] typesafe_cb: wrappers for typesafe callbacks. | Date | Mon, 21 Apr 2008 09:01:19 +1000 |
| |
cast_if_type is clever but annoying to use, so we make some slightly less annoying wrappers for callback registration.
These allow const pointer-taking functions as well as the normal non-const ones (volatile variant omitted for simplicity). We also have a typesafe_cb_preargs() for callbacks which don't just take one argument.
Here's an example of use:
BEFORE: void foo_set_callback(int (*callback)(void *), void *arg);
AFTER: #define foo_set_callback(cb, arg) \ __foo_set_callback(typesafe_cb(int, (cb), (arg)), (arg)) void __foo_set_callback(int (*callback)(void *), void *arg);
o If cb is of form "int cb(typeof(arg))" or "int cb(const typeof(arg))" it will be cast to form "int cb(void *)". o Otherwise, if cb is not already of form "int cb(void *)" it will cause a warning when passed to __foo_set_callback(). o If arg is not a pointer, then handing it to __foo_set_callback() will cause a warning.
Note: there are at least two possible additions we don't yet need. We don't cover callbacks which take a volatile pointer, even though that would be fine, and we don't have a typesafe_cb_postargs().
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> --- include/linux/kernel.h | 63 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+)
diff -r 907c55be656f include/linux/kernel.h --- a/include/linux/kernel.h Mon Apr 21 06:58:00 2008 +1000 +++ b/include/linux/kernel.h Mon Apr 21 07:04:02 2008 +1000 @@ -436,4 +436,39 @@ struct sysinfo { #define NUMA_BUILD 0 #endif +/* If fn is of type ok1 or ok2, cast to desttype */ +#define __typesafe_cb(desttype, fn, ok1, ok2) \ + cast_if_type(cast_if_type((fn), ok1, desttype), ok2, desttype) + +/** + * typesafe_cb - cast a callback function if it matches the arg + * @rettype: the return type of the callback function + * @fn: the callback function to cast + * @arg: the (pointer) argument to hand to the callback function. + * + * If a callback function takes a single argument, this macro does + * appropriate casts to a function which takes a single void * argument if the + * callback provided matches the @arg (or a const or volatile version). + * + * It is assumed that @arg is of pointer type: usually @arg is passed + * or assigned to a void * elsewhere anyway. + */ +#define typesafe_cb(rettype, fn, arg) \ + __typesafe_cb(rettype (*)(void *), (fn), \ + rettype (*)(const typeof(arg)), \ + rettype (*)(typeof(arg))) + +/** + * typesafe_cb_preargs - cast a callback function if it matches the arg + * @rettype: the return type of the callback function + * @fn: the callback function to cast + * @arg: the (pointer) argument to hand to the callback function. + * + * This is a version of typesafe_cb() for callbacks that take other arguments + * before the @arg. + */ +#define typesafe_cb_preargs(rettype, fn, arg, ...) \ + __typesafe_cb(rettype (*)(__VA_ARGS__, void *), (fn), \ + rettype (*)(__VA_ARGS__, const typeof(arg)), \ + rettype (*)(__VA_ARGS__, typeof(arg))) #endif
| |