2016-10-04 5 views
1

Ich bin neu bei libusb, so verstehe ich es nicht wirklich sehr gut. Ich versuche, etwas USB-Kommunikation zu machen.Libusb hängt bei der Verwendung von C++ 11 async

Ich verwende die Hotplug-Funktion, die ganz gut funktioniert. Also dachte ich, wenn ich ein Gerät eintreffen Ereignis, würde ich alle Kommunikation mit USB auf einem anderen Thread mit der asynchronen Funktion C++11 tun, so dass ich synchrone I/O mit mehreren Geräten zu einfachen Codes tun könnte. Ihre asynchrone I/O ist ein bisschen verwirrend für mich. Hoffentlich kann ich die synchrone I/O mit C++ asynchronen Feature verwenden.

Aber ich habe ein Problem, wo einige libusb Aufruf zu hängen scheinen, wenn der Code in C++ 11 asynchrone Feature ausgeführt wird. Wenn es nicht in der asynchronen C++ 11-Funktion ausgeführt wird, funktioniert es problemlos.

Also nehme ich an, dass es meine C++ 11 asynchrone Feature-Code ist, dass das Problem ist.

Hier ist mein Hotplug-Rückruf:

int LIBUSB_CALL hotplug_callback(libusb_context *ctx, libusb_device *dev, libusb_hotplug_event event, void *user_data) 
{ 
    std::future<void> result(std::async([] (libusb_device *d) { 

    libusb_device_handle *h; 

    printf("%s\n", "Opening"); 
    int rc = libusb_open(d, &h); 
    if(rc != LIBUSB_SUCCESS) { 
     printf("ERROR: %s\n", libusb_error_name(rc)); 
     return; 
    } 
    printf("%s\n", "Opened"); 

    printf("%s\n", "Closing"); 
    libusb_close(h); 
    printf("%s\n", "Closed!"); 

    }, dev)); 

    result.get(); 

    return 0; 
} 

Also mit diesem Code auf libusb_close Es gibt

hängt:

Opening 
Opened 
Closing 

Der Haupt Code sieht wie folgt aus:

int main(int argc, char* argv[]) { 

    int vendor_id = 0x1234; 
    int product_id = 0x4556; 

    libusb_hotplug_callback_handle *hp = nullptr; 
    libusb_context *context = nullptr; 
    int rc = libusb_init(&context); 

    if(rc < 0) 
    { 
    return rc; 
    } 

    libusb_set_debug(context, LIBUSB_LOG_LEVEL_WARNING); 

    rc = libusb_hotplug_register_callback(
    context, 
    LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 
    LIBUSB_HOTPLUG_NO_FLAGS, 
    vendor_id, 
    product_id, 
    LIBUSB_HOTPLUG_MATCH_ANY, 
    hotplug_callback, 
    NULL, 
    hp 
    ); 

    if (LIBUSB_SUCCESS != rc) { 
    libusb_exit (context); 
    return rc; 
    } 

    while(1) { 
    rc = libusb_handle_events(context); 
    } 

    return 0; 
} 

Wohlgemerkt, dieser Code ist eher prototypisch, daher ist er nicht wirklich gut geschrieben. Es befindet sich immer noch im Explorationsmodus von libusb.

Antwort

3

According to their own website, die Verwendung von Multi-Threading mit libusb (und std::async ist im Wesentlichen Multi-Threading, wenn es nicht serialisiert ist) erfordert einige Überlegungen.

Zum Beispiel sie speziell Zustand:

libusb_close() einen Dateideskriptor aus der Umfrage Satz entfernen. Es gibt alle Arten von Race Conditions, die hier auftreten können, daher ist es wichtig, dass niemand zu diesem Zeitpunkt Event-Handling durchführt.

In Ihrem Code, gibt es keine Synchronisation zwischen dem Aufruf von libusb_close in dem einem Faden und libusb_handle_events in dem anderes. Verwandte (wie oben von der gleichen Quelle):

Das Problem ist, dass, wenn zwei oder mehr Threads gleichzeitig Umfrage fordern() oder wählen Sie() auf libusb der Datei-Deskriptoren dann nur eines dieser Themen geweckt werden, wenn Ein Ereignis kommt an. Die anderen werden völlig vergessen, dass irgendetwas passiert ist.

Es ist durchaus vorstellbar, dass das, was hier passiert ist, dass libusb_handle_events im Hauptthread wird das „Stehlen“ ein Ereignis, das libusb_close für wartet, so dass es nie wieder.

Unterm Strich ist, dass Sie müssen entweder:

  1. den verlinkten Artikeln folgen, die im Detail erläutert, wie mit Multi-Threading verwenden Libusb oder
  2. die asynchrone API von libusb verstehen und macht Verwenden Sie stattdessen.
+0

Danke, ich ging schließlich für ihre asynchrone API – pdiddy

Verwandte Themen