The seemingly unnecessary generality of the alternate object database callback infrastructure suggests that there are plans for passing around not only callbacks to callbacks, but also arbitrary data to callbacks. Unfortunately, as discussed in the previous commit's message, C[99] does not allow for values of type pointer to function to be stored in variables of type pointer to void. The only unified solution, then, is to pass around a value of type union of both pointer to function and pointer to void; this solution is voiced here as well: http://www.safercode.com/blog/2008/11/25/generic-function-pointers-in-c-and-void.html That article states: How can I use the same variable for object / data ------------------------------------------------- and function pointers inter-changeably? --------------------------------------- Simple, use a union of a void * and the function pointer (like we described above) and you need not worry about the size because the compiler will automatically choose the largest size for this union which can hold a function pointer. This commit introduces such a union and a couple of macros for using it effectively. Signed-off-by: Michael Witten <mfwitten@xxxxxxxxx> --- builtin/fetch-pack.c | 3 ++- builtin/receive-pack.c | 3 ++- cache.h | 16 ++++++++++++++-- sha1_file.c | 4 ++-- transport.c | 4 ++-- transport.h | 2 +- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c index ded1784..737b382 100644 --- a/builtin/fetch-pack.c +++ b/builtin/fetch-pack.c @@ -225,7 +225,8 @@ static void insert_one_alternate_ref(const struct ref *ref, void *unused) static void insert_alternate_refs(void) { + ALT_ODB_FN_INFO_FUNC(info,insert_one_alternate_ref); - foreach_alt_odb(refs_from_alternate_cb, (alt_odb_fn_cb)insert_one_alternate_ref); + foreach_alt_odb(refs_from_alternate_cb, info); } #define INITIAL_FLUSH 16 diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c index 4ce9241..51e66d2 100644 --- a/builtin/receive-pack.c +++ b/builtin/receive-pack.c @@ -738,7 +738,8 @@ static void add_one_alternate_ref(const struct ref *ref, void *unused) static void add_alternate_refs(void) { + ALT_ODB_FN_INFO_FUNC(info,add_one_alternate_ref); - foreach_alt_odb(refs_from_alternate_cb, (alt_odb_fn_cb)add_one_alternate_ref); + foreach_alt_odb(refs_from_alternate_cb, info); } int cmd_receive_pack(int argc, const char **argv, const char *prefix) diff --git a/cache.h b/cache.h index ab3407a..ca8574a 100644 --- a/cache.h +++ b/cache.h @@ -893,8 +893,20 @@ extern struct alternate_object_database { extern void prepare_alt_odb(void); extern void add_to_alternates_file(const char *reference); typedef void (*alt_odb_fn_cb)(void); +union alt_odb_fn_info { + alt_odb_fn_cb func; + void *data; +}; +#define ALT_ODB_FN_INFO_FUNC(variable, function) \ + union alt_odb_fn_info variable = { \ + .func = (alt_odb_fn_cb)function \ + } +#define ALT_ODB_FN_INFO_DATA(variable, data_) \ + union alt_odb_fn_info variable = { \ + .data = data_ \ + } -typedef int (*alt_odb_fn)(struct alternate_object_database *, alt_odb_fn_cb); +typedef int (*alt_odb_fn)(struct alternate_object_database *, union alt_odb_fn_info); -extern void foreach_alt_odb(alt_odb_fn, alt_odb_fn_cb); +extern void foreach_alt_odb(alt_odb_fn, union alt_odb_fn_info); struct pack_window { struct pack_window *next; diff --git a/sha1_file.c b/sha1_file.c index 8555dbe..2709fea 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -388,13 +388,13 @@ void add_to_alternates_file(const char *reference) link_alt_odb_entries(alt, alt + strlen(alt), '\n', NULL, 0); } -void foreach_alt_odb(alt_odb_fn fn, alt_odb_fn_cb cb) +void foreach_alt_odb(alt_odb_fn fn, union alt_odb_fn_info info) { struct alternate_object_database *ent; prepare_alt_odb(); for (ent = alt_odb_list; ent; ent = ent->next) - if (fn(ent, cb)) + if (fn(ent, info)) return; } diff --git a/transport.c b/transport.c index f572fa8..3b44b27 100644 --- a/transport.c +++ b/transport.c @@ -1190,14 +1190,14 @@ literal_copy: return xstrdup(url); } -int refs_from_alternate_cb(struct alternate_object_database *e, alt_odb_fn_cb cb) +int refs_from_alternate_cb(struct alternate_object_database *e, union alt_odb_fn_info info) { char *other; size_t len; struct remote *remote; struct transport *transport; const struct ref *extra; - alternate_ref_fn ref_fn = (alternate_ref_fn)cb; + alternate_ref_fn ref_fn = (alternate_ref_fn)info.func; e->name[-1] = '\0'; other = xstrdup(real_path(e->base)); diff --git a/transport.h b/transport.h index 47ea41a..d00e547 100644 --- a/transport.h +++ b/transport.h @@ -167,6 +167,6 @@ void transport_print_push_status(const char *dest, struct ref *refs, int verbose, int porcelain, int *nonfastforward); typedef void (*alternate_ref_fn)(const struct ref *, void *); -extern int refs_from_alternate_cb(struct alternate_object_database *e, alt_odb_fn_cb cb); +extern int refs_from_alternate_cb(struct alternate_object_database *e, union alt_odb_fn_info info); #endif -- 1.7.4.2.417.g32d76d -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html