Re: [PATCH kvm-unit-tests 2/4] Introduce a C++ wrapper for the kvm APIs

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

 



On 11/28/2010 04:28 PM, Michael S. Tsirkin wrote:

But rather need to use ugly factory functions with all sorts of
DO_UPCAST.  This is really unfriendly especially for writing test
cases.
Yes, I agree. Just moving memory allocation out of there
will fix most of the ugliness.

So here's a short list of things I've been working on that I don't believe have nice implementations in C.

1) Factories with string based parameters with natural constructor arguments.

I want to have:

I8254(DriftMode mode)

or:

void i8254_init(I8524 *self, DriftMode mode)

And either be able to directly instantiate the object or create it with the following command:

dev = create("i8524", "mode", "catchup", NULL);

In C++, I can do:

static Device *i8524_create(DriftMode mode)
{
     return new I8524(mode);
}

//...
add_factory("i8524", i8524_create, "mode");

This works because we can use templates to figure out the argument type to create and automatically set things up for the mode parameter. Because of overloading, we can have variable arguments so this works for 1, 2, or 10 arguments. In C, at best you would have to do something like:

static Device *i8524_create(ParameterList *list)
{
    DriftMode mode;
    I8524 *i8524;
    if (param_list_has(list, "mode")) {
         // should we check the type?
mode = (DriftMode)param_get_as_int(list, "mode"); // or do we teach param about DriftMode?
    } else {
         // should we error?
    }
    i8524 = malloc(sizeof(*i8524));
    if (i8524) {
        return &i8524->dev; // I have to know how to get to this
    }
    return NULL;
}

struct factory_info i8524_info = {
    .args = (FactoryArgument[]){
         { "mode", "DriftMode" },
         { }
    }
};

add_factory("i8524", i8524_create, i8524_info);

And there's so many bad decisions I can make in the process. Do I have a mechanism to register new types external to the system and make all types convertable?

My C++ example uses a template specialization to convert from types to strings. It's simple and extensible. There's no list that needs to be kept at run time because the compiler does all of the book keeping.

I can let the compiler figure out how to go from I8524 to Device * because it knows how to.

The same is true for generic get/set properties. In C++, I can do something like:

class I8524 : public PropertyAccessible {
public:
    enum LinkStatus {
        LINK_UP,
        LINK_DOWN,
    };
    LinkStatus get_link_status(void);
    void set_link_status(void);
};

template <>
I8254::LinkStatus type_from_str(std::string value)
{
     if (value == "Down") {
          return LINK_DOWN;
     } else if (value == "Up") {
          return LINK_UP;
     }
     throw new InvalidTypeConversionException("LinkStatus", value);
}

template <>
std::string type_to_str(I8254::LinkStatus status)
{
    if (status == LINK_DOWN) {
        return "Down";
    } else {
        return "Up";
    }
}

I8524::I8524(void) {
this->add_property("link_status", &I8524::get_link_status, &I8524::set_link_status);
}

And now I can do:

Device *dev = new I8524();

cout << dev->get("link_status") << endl;

And it will print: Down

Simple and elegant. The main class has strong error checking, adding the property is absolutely painless, supporting new types is absolutely painless. The actual class implementation never sees a string--ever. There is only one place string->type conversion happens.

I'm not going to show the C version because I know what it involves and I suspect you do too. It totally sucks and I don't want to spend my Sunday evening writing it. And that's really my motivation for using C++. I get tired of doing the work that the compiler should be doing for me. I want to spend my time doing interesting things like writing device model test cases instead of writing code to work around the fact that the C type system is about as powerful as a Vespa.

Regars,

Anthony Liguori
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux