[RFC 2/2] Future Proofing: Pass around pointers to either functions or data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]