假设我有一个只使用hotplug API的libusb程序。你注册了一个回调,然后显然必须在循环中调用libusb_handle_events()
,然后调用你的hotplug回调。
int LIBUSB_CALL hotplugCallback(libusb_context* ctx,
libusb_device* device,
libusb_hotplug_event event,
void* user_data)
{
cout << "Device plugged in or unplugged";
}
void main()
{
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
for (;;)
{
if (libusb_handle_events_completed(nullptr, nullptr) != LIBUSB_SUCCESS)
return 1;
}
return 0;
}
问题是,没有超时黑客如何彻底退出此事件循环?我无法找到任何强制libusb_handle_events()
(或libusb_handle_events_completed()
)返回的函数。理论上他们可能永远不会回来。
答案 0 :(得分:4)
对不起,如果迟到了。
本来可以更好地表达该问题,但我假设(根据您的评论更新)您的实际程序类似于以下内容:
int LIBUSB_CALL hotplugCallback(libusb_context *ctx,
libusb_device *device,
libusb_hotplug_event event,
void *user_data) {
cout << "Device plugged in or unplugged";
}
void SomeClass::someFunction() {
libusb_init(nullptr);
libusb_hotplug_register_callback(nullptr,
static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
LIBUSB_HOTPLUG_NO_FLAGS,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
LIBUSB_HOTPLUG_MATCH_ANY,
&hotplugCallback,
this,
&hotplugCallbackHandle);
this->thread = std::thread([this]() {
while (this->handlingEvents) {
int error = libusb_handle_events_completed(context, nullptr);
}
});
}
比方说,您的对象已被释放,并且无论USB总线上发生了什么,您都不在乎,您想清理线程。
您求反this->handlingEvents
,然后调用thread.join()
,线程挂起60秒,然后恢复执行。
之所以这样做,是因为libusb_handle_events_completed
的默认行为会调用libusb_handle_events_timeout_completed
,并在60秒的超时间隔内传递并计划使其无限。
强制执行的方式 libusb_handle_events_completed
返回是您叫libusb_hotplug_deregister_callback
,它将唤醒libusb_handle_events()
,从而使函数返回
docs中有关于此行为的更多信息。
因此您的类的析构函数(或您想立即停止监听的任何地方)可能看起来像这样:
SomeClass::~SomeClass() {
this->handlingEvents = false;
libusb_hotplug_deregister_callback(context, hotplugCallbackHandle);
if (this->thread.joinable()) this->thread.join();
libusb_exit(this->context);
}
答案 1 :(得分:0)
在功能中:
int libusb_handle_events_completed(libusb_context* ctx, int* completed)
您可以将已完成的值更改为&#34; 1&#34;所以函数将无阻塞地返回
根据他们的文件:
如果参数complete不是NULL,则在获取事件后 处理锁定此函数将立即返回整数 指向不是0.这允许无竞赛等待 完成特定的转移。
答案 2 :(得分:0)
libusb中没有强制libusb_handle_events()
返回的函数。
建议在专用线程中使用libusb_handle_events()
,以免您的主线程被此调用阻塞。即使,如果您需要操纵事件处理程序的调用,也可以将调用置于while(condition)并在主线程中更改条件状态。
Libusb文档详细介绍了此here。