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

Re: [Xen-devel] [PATCH v4 2/6] golang/xenlight: begin Go to C type marshaling



> I realize this is all generated code, but there's still a massive amount
> of duplication here, which will at very least cause code bloat.  I think
> it should be possible to do this all at once with a defer, like this:
>
> func (x *SpiceInfo) toC() (xc C.libxl_spice_info, err error) {
>     C.libxl_spice_info_init(&xc)
>     defer func () {
>         if err != nil {
>             libxl_spice_info_dispose(&xc);
>         }
>     }()
>
> What do you think?

That was my intention a while ago (one of the reasons I named the
return values in toC), but I forgot to make the change. Thanks.

> The other comment I have right now is about the return-by-value rather
> than by reference.  It does mean you can do things like:
>
>     cfoo, err := gfoo.toC()
>
> rather than
>
>     var cfoo C.libxl_foo
>     err := gfoo.toC(&cfoo)
> But it means there's an inordinate amount of copying.  Every structure
> at depth N will be copied N times; and some of these substructures are
> quite large.  Because we're returning errors from toC(), we're never
> going to be able to do something like
>
>     C.libxl_bar(Ctx.ctx, gfoo.toC())
>
> anyway.  If we switched to passing in pointers (and used the defer trick
> above), a lot of these could end up looking like this:
>
>     if err = x.DisableTicketing.toC(&xc.disable_ticketing); err != nil {
>         return err
>     }
>
> Avoiding the copy.  What do you think?

That makes sense to me. I'd like to avoid excessive copying, and
that's an easy change to make.

> The final thing is actually whether we want to do the "_init" at the
> beginning of the function at all.  The _init functions have two purposes:
>
> 1. To zero out the structures
> 2. To set things to default values.
>
> In Go, #1 isn't necessary; structures are defined as zeroed.  In .toC(),
> #2 won't be effective either in most cases, since we'll be writing over
> values with the values found in the Go struct.

Yes that's true, I guess it is mostly ineffectual then.

> To get the default values, I think we'll probably need to write helpers
> like this:
>
> func NewDomainConfig(t DomainType) (*DomainConfig, error) {
>         var cconfig C.libxl_domain_config
>
>         C.libxl_domain_config_init(&cconfig)
>         C.libxl_domain_build_info_init_type(&cconfig.b_info,
> C.libxl_domain_type(t))
>
>         gconfig := &DomainConfig{}
>         err := gconfig.fromC(&cconfig)
>         if err != nil {
>                 return nil, err
>         }
>
>         return gconfig, nil
> }
>
> This makes sure that not only DomainConfig has the right default values,
> but that DomainConfig.BuildInfo.TypeUnion has the right default values
> for HVM guests.

Sounds good to me. It seems like it should be easy enough to generate
those helpers.

> So the only time #2 would have any effect in .toC() would be if there
> was a field in a structure that the Go bindings didn't know about.  I
> kind of go back and forth as to how necessary that is.
>
> Any thoughts?

Would the Go bindings not know about the field because it's something
internal? Or are you thinking a case where the bindings are out of
sync with libxl? In the former case, I'm not familiar enough with the
internal types to foresee potential issues. In the latter, I would
think the misalignment would be the larger issue. Given what you said
above, it doesn't feel all that necessary.

-NR

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.