Add two new fields, cblifetime and cbcount, to the `closure` type
in generator/API.ml*. cblifetime tells if the closure may only be used
for as long as the command is in flight or if the closure may be used
until the handle is destructed. cbcount tells whether the closure may
be called many times or just once.
This information is needed in the Rust bindings for:
a) Knowing if the closure trait should be FnMut or FnOnce
(see <
https://doc.rust-lang.org/std/ops/trait.FnOnce.html>).
b) Knowing for what lifetime the closure should be valid. A closure that
may be called after the function invokation has returned must live
for the `'static` lietime. But static closures are inconveniant for
the user since they can't effectively borrow any local data. So it is
good if this restriction is relaxed when it is not needed.
---
generator/API.ml | 20 ++++++++++++++++++++
generator/API.mli | 17 +++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/generator/API.ml b/generator/API.ml
index 99fcb82..41a6dd1 100644
--- a/generator/API.ml
+++ b/generator/API.ml
@@ -77,6 +77,8 @@ and ret =
and closure = {
cbname : string;
cbargs : cbarg list;
+ cblifetime : cblifetime;
+ cbcount : cbcount
}
and cbarg =
| CBArrayAndLen of arg * string
@@ -87,6 +89,12 @@ and cbarg =
| CBString of string
| CBUInt of string
| CBUInt64 of string
+and cblifetime =
+| CBCommand
+| CBHandle
+and cbcount =
+| CBOnce
+| CBMany
and enum = {
enum_prefix : string;
enums : (string * int) list
@@ -141,20 +149,28 @@ the handle from the NBD protocol handshake."
(* Closures. *)
let chunk_closure = {
cbname = "chunk";
+ cblifetime = CBCommand;
+ cbcount = CBMany;
cbargs = [ CBBytesIn ("subbuf", "count");
CBUInt64 "offset"; CBUInt "status";
CBMutable (Int "error") ]
}
let completion_closure = {
cbname = "completion";
+ cblifetime = CBCommand;
+ cbcount = CBOnce;
cbargs = [ CBMutable (Int "error") ]
}
let debug_closure = {
cbname = "debug";
+ cblifetime = CBHandle;
+ cbcount = CBMany;
cbargs = [ CBString "context"; CBString "msg" ]
}
let extent_closure = {
cbname = "extent";
+ cblifetime = CBCommand;
+ cbcount = CBMany;
cbargs = [ CBString "metacontext";
CBUInt64 "offset";
CBArrayAndLen (UInt32 "entries",
@@ -163,10 +179,14 @@ let extent_closure = {
}
let list_closure = {
cbname = "list";
+ cblifetime = CBCommand;
+ cbcount = CBMany;
cbargs = [ CBString "name"; CBString "description" ]
}
let context_closure = {
cbname = "context";
+ cblifetime = CBCommand;
+ cbcount = CBMany;
cbargs = [ CBString "name" ]
}
let all_closures = [ chunk_closure; completion_closure;
diff --git a/generator/API.mli b/generator/API.mli
index 361132d..ff85849 100644
--- a/generator/API.mli
+++ b/generator/API.mli
@@ -94,6 +94,12 @@ and ret =
and closure = {
cbname : string; (** name of callback function *)
cbargs : cbarg list; (** all closures return int for now *)
+ (** An upper bound of the lifetime of the closure. Either it will be used for
+ as long as the command is in flight or it may be used until the handle
+ is destructed. *)
+ cblifetime : cblifetime;
+ (** Whether the callback may only be called once or many times. *)
+ cbcount : cbcount;
}
and cbarg =
| CBArrayAndLen of arg * string (** array + number of entries *)
@@ -104,6 +110,17 @@ and cbarg =
| CBString of string (** like String *)
| CBUInt of string (** like UInt *)
| CBUInt64 of string (** like UInt64 *)
+and cblifetime =
+| CBCommand (** The closure may only be used until the command is retired.
+ (E.G., completion callback or list callback.) *)
+| CBHandle (** The closure might be used until the handle is descructed.
+ (E.G., debug callback.) *)
+and cbcount =
+| CBOnce (** The closure will be used 0 or 1 time if the aio_* call returned an
+ error and exactly once if the call succeeded.
+ (E.g., completion callback.) *)
+| CBMany (** The closure may be used any number of times.
+ (E.g., list callback.) *)
and enum = {
enum_prefix : string; (** prefix of each enum variant *)
enums : (string * int) list (** enum names and their values in C *)
--
2.41.0