[Libguestfs] [PATCH libnbd v2 05/10] generator: ocaml: Define a struct user_data and common free function.

Richard W.M. Jones rjones at redhat.com
Thu Aug 15 09:56:16 UTC 2019


Just a simple refactoring.
---
 generator/generator | 71 +++++++++++++++++++++++++++------------------
 1 file changed, 43 insertions(+), 28 deletions(-)

diff --git a/generator/generator b/generator/generator
index 98c99e0..35936c6 100755
--- a/generator/generator
+++ b/generator/generator
@@ -4945,7 +4945,8 @@ let print_ocaml_closure_wrapper { cbname; cbargs } =
   assert (List.length argnames <= 5);
   pr "  CAMLlocal%d (%s);\n" (List.length argnames)
     (String.concat ", " argnames);
-  pr "  CAMLlocal3 (fnv, exn, rv);\n";
+  pr "  CAMLlocal2 (exn, rv);\n";
+  pr "  const struct user_data *data = user_data;\n";
   pr "  int r;\n";
   pr "  value args[%d];\n" (List.length argnames);
   pr "\n";
@@ -4974,9 +4975,7 @@ let print_ocaml_closure_wrapper { cbname; cbargs } =
 
   List.iteri (fun i n -> pr "  args[%d] = %s;\n" i n) argnames;
 
-  pr "  fnv = * (value *) user_data;\n";
-
-  pr "  rv = caml_callbackN_exn (fnv, %d, args);\n"
+  pr "  rv = caml_callbackN_exn (data->fnv, %d, args);\n"
     (List.length argnames);
 
   List.iter (
@@ -5039,15 +5038,7 @@ let print_ocaml_closure_wrapper { cbname; cbargs } =
   pr ";\n";
   pr "  caml_enter_blocking_section ();\n";
   pr "  return ret;\n";
-  pr "}\n";
-
-  pr "static void\n";
-  pr "%s_free (void *user_data)\n" cbname;
-  pr "{\n";
-  pr "  caml_remove_generational_global_root (user_data);\n";
-  pr "  free (user_data);\n";
-  pr "}\n";
-  pr "\n"
+  pr "}\n"
 
 let print_ocaml_binding (name, { args; optargs; ret }) =
   (* Get the names of all the value arguments including the handle. *)
@@ -5098,14 +5089,13 @@ let print_ocaml_binding (name, { args; optargs; ret }) =
        pr "    /* The function may save a reference to the closure, so we\n";
        pr "     * must treat it as a possible GC root.\n";
        pr "     */\n";
-       pr "    %s_callback.user_data = malloc (sizeof (value));\n" cbname;
-       pr "    if (%s_callback.user_data == NULL)\n" cbname;
-       pr "      caml_raise_out_of_memory ();\n";
-       pr "    *(value *)%s_callback.user_data = Field (%sv, 0);\n"
-         cbname cbname;
-       pr "    caml_register_generational_global_root (%s_callback.user_data);\n" cbname;
+       pr "    struct user_data *user_data = alloc_user_data ();\n";
+       pr "\n";
+       pr "    user_data->fnv = Field (%sv, 0);\n" cbname;
+       pr "    caml_register_generational_global_root (&user_data->fnv);\n";
        pr "    %s_callback.callback = %s_wrapper;\n" cbname cbname;
-       pr "    %s_callback.free = %s_free;\n" cbname cbname;
+       pr "    %s_callback.user_data = user_data;\n" cbname;
+       pr "    %s_callback.free = free_user_data;\n" cbname;
        pr "  }\n";
     | OFlags (n, { flag_prefix }) ->
        pr "  uint32_t %s;\n" n;
@@ -5138,14 +5128,13 @@ let print_ocaml_binding (name, { args; optargs; ret }) =
        pr "  /* The function may save a reference to the closure, so we\n";
        pr "   * must treat it as a possible GC root.\n";
        pr "   */\n";
-       pr "  nbd_%s_callback %s_callback = { .callback = %s_wrapper, .free = %s_free };\n"
-         cbname cbname cbname cbname;
-       pr "  %s_callback.user_data = malloc (sizeof (value));\n" cbname;
-       pr "  if (%s_callback.user_data == NULL) caml_raise_out_of_memory ();\n"
-         cbname;
-       pr "  *(value *)%s_callback.user_data = %sv;\n" cbname cbname;
-       pr "  caml_register_generational_global_root (%s_callback.user_data);\n"
-         cbname
+       pr "  struct user_data *user_data = alloc_user_data ();\n";
+       pr "  user_data->fnv = %sv;\n" cbname;
+       pr "  caml_register_generational_global_root (&user_data->fnv);\n";
+       pr "  nbd_%s_callback %s_callback;\n" cbname cbname;
+       pr "  %s_callback.callback = %s_wrapper;\n" cbname cbname;
+       pr "  %s_callback.user_data = user_data;\n" cbname;
+       pr "  %s_callback.free = free_user_data;\n" cbname
     | Enum (n, { enum_prefix }) ->
        pr "  int %s = %s_val (%sv);\n" n enum_prefix n
     | Flags (n, { flag_prefix }) ->
@@ -5264,6 +5253,32 @@ let generate_ocaml_nbd_c () =
   pr "#pragma GCC diagnostic ignored \"-Wmissing-prototypes\"\n";
   pr "\n";
 
+  pr "/* This is passed to *_wrapper as the user_data pointer";
+  pr " * and freed in the free_user_data function below.\n";
+  pr " */\n";
+  pr "struct user_data {\n";
+  pr "  value fnv;      /* GC root pointing to OCaml function. */\n";
+  pr "};\n";
+  pr "\n";
+  pr "static struct user_data *\n";
+  pr "alloc_user_data (void)\n";
+  pr "{\n";
+  pr "  struct user_data *data = calloc (1, sizeof *data);\n";
+  pr "  if (data == NULL)\n";
+  pr "    caml_raise_out_of_memory ();\n";
+  pr "  return data;\n";
+  pr "}\n";
+  pr "\n";
+  pr "static void\n";
+  pr "free_user_data (void *user_data)\n";
+  pr "{\n";
+  pr "  struct user_data *data = user_data;\n";
+  pr "\n";
+  pr "  caml_remove_generational_global_root (&data->fnv);\n";
+  pr "  free (data);\n";
+  pr "}\n";
+  pr "\n";
+
   List.iter print_ocaml_closure_wrapper all_closures;
   List.iter print_ocaml_enum_val all_enums;
   List.iter print_ocaml_flag_val all_flags;
-- 
2.22.0




More information about the Libguestfs mailing list